From 01fb34a1bd08e2b7ea37af5814f130c8e32f00c7 Mon Sep 17 00:00:00 2001 From: HapeLee <63206378+HapeLee@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:28:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 5 + .../java/io/legado/app/data/dao/BookDao.kt | 14 + .../io/legado/app/ui/about/AboutScreen.kt | 18 +- .../io/legado/app/ui/about/AppLogSheet.kt | 21 +- .../app/ui/book/bookmark/AllBookmarkScreen.kt | 16 +- .../app/ui/book/explore/ExploreShowScreen.kt | 73 +++-- .../app/ui/book/group/GroupEditSheet.kt | 14 +- .../ui/book/import/remote/RemoteBookScreen.kt | 65 ++--- .../ui/book/info/edit/BookInfoEditScreen.kt | 22 +- .../ui/book/readRecord/ReadRecordScreen.kt | 103 ++++--- .../book/searchContent/SearchContentScreen.kt | 35 ++- .../io/legado/app/ui/book/toc/TocScreen.kt | 47 ++-- .../app/ui/book/toc/rule/TxtRuleScreen.kt | 18 +- .../legado/app/ui/config/ConfigNavScreen.kt | 7 +- .../config/backupConfig/BackupConfigScreen.kt | 44 ++- .../config/coverConfig/CoverConfigScreen.kt | 7 +- .../ui/config/coverConfig/CoverManageSheet.kt | 7 +- .../coverConfig/CoverRuleConfigSheet.kt | 18 +- .../otherConfig/CheckSourceBottomSheet.kt | 11 +- .../DirectLinkUploadBottomSheet.kt | 33 +-- .../config/otherConfig/OtherConfigScreen.kt | 41 +-- .../app/ui/config/readConfig/PageKeySheet.kt | 19 +- .../ui/config/readConfig/ReadConfigScreen.kt | 9 +- .../themeConfig/BackgroundImageManageSheet.kt | 7 +- .../themeConfig/LauncherIconPickerSheet.kt | 7 +- .../app/ui/config/themeConfig/ThemeConfig.kt | 3 + .../config/themeConfig/ThemeConfigScreen.kt | 36 ++- .../ui/config/themeConfig/ThemeListDialog.kt | 32 ++- .../app/ui/dict/rule/DictRuleEditSheet.kt | 14 +- .../legado/app/ui/dict/rule/DictRuleScreen.kt | 18 +- .../io/legado/app/ui/main/MainActivity.kt | 8 +- .../io/legado/app/ui/main/MainDestination.kt | 53 ++-- .../java/io/legado/app/ui/main/MainScreen.kt | 116 ++------ .../legado/app/ui/main/bookshelf/BookItem.kt | 33 +-- .../app/ui/main/bookshelf/BookShelfItem.kt | 4 + .../ui/main/bookshelf/BookshelfConfigSheet.kt | 7 +- .../app/ui/main/bookshelf/BookshelfScreen.kt | 68 ++--- .../app/ui/main/bookshelf/GroupManageSheet.kt | 7 +- .../app/ui/main/explore/ExploreScreen.kt | 69 ++--- .../java/io/legado/app/ui/main/my/MyScreen.kt | 147 ++++++---- .../io/legado/app/ui/main/rss/RssScreen.kt | 31 +-- .../app/ui/replace/ReplaceRuleScreen.kt | 76 ++---- .../app/ui/replace/edit/ReplaceEditScreen.kt | 58 ++-- .../ui/rss/favorites/RssFavoritesScreen.kt | 14 +- .../ui/rss/source/manage/RssSourceScreen.kt | 42 +-- .../app/ui/rss/subscription/RuleSubScreen.kt | 24 +- .../io/legado/app/ui/theme/AdaptivePadding.kt | 19 ++ .../java/io/legado/app/ui/theme/AppTheme.kt | 77 +++++- .../java/io/legado/app/ui/theme/HazeStyle.kt | 8 +- .../io/legado/app/ui/theme/LegadoTheme.kt | 85 ++++++ .../io/legado/app/ui/theme/ThemeResolver.kt | 12 + .../java/io/legado/app/ui/theme/Typography.kt | 44 +++ .../app/ui/theme/hazeStyle/HazeLegado.kt | 48 ++++ .../legado/app/ui/widget/CollapsibleHeader.kt | 11 +- .../app/ui/widget/components/AnimatedText.kt | 6 +- .../components/AppFloatingActionButton.kt | 56 ++++ .../ui/widget/components/AppNavigationBar.kt | 93 +++++++ .../app/ui/widget/components/AppScaffold.kt | 113 ++++---- .../ui/widget/components/EmptyMessageView.kt | 4 +- .../GlassMediumFlexibleTopAppBar.kt | 113 -------- .../components/GroupManageBottomSheet.kt | 9 +- .../app/ui/widget/components/IconSwitch.kt | 34 +++ .../ui/widget/components/SearchBarSection.kt | 4 +- .../widget/components/SelectionBottomBar.kt | 6 +- .../widget/components/SplicedColumnGroup.kt | 41 +-- .../components/bookmark/BookmarkEditSheet.kt | 23 +- .../components/bookmark/BookmarkItem.kt | 15 +- .../widget/components/button/AlertButton.kt | 4 +- .../components/button/AnimatedActionButton.kt | 8 +- .../components/button/AnimatedTextButton.kt | 4 +- .../components/button/MiuixBackButton.kt | 57 ++++ .../components/button/SmallIconButton.kt | 47 ++-- .../components/button/SmallTextButton.kt | 7 +- .../widget/components/button/TopBarButton.kt | 131 +++++---- .../ui/widget/components/card/GlassCard.kt | 140 +++++++--- .../components/card/SelectionItemCard.kt | 67 +++-- .../ui/widget/components/card/SettingCard.kt | 75 ++++++ .../app/ui/widget/components/card/TextCard.kt | 26 +- .../components/checkBox/CheckboxItem.kt | 7 +- .../widget/components/cover/BookshelfCover.kt | 22 +- .../components/dialog/ColorPickerSheet.kt | 15 +- .../components/dialog/TextListInputDialog.kt | 18 +- .../components/divider/PillHeaderDivider.kt | 7 +- .../components/filePicker/FilePickerSheet.kt | 11 +- .../heatmap/HeatmapCalendarComponents.kt | 19 +- .../app/ui/widget/components/icon/AppIcon.kt | 37 +++ .../importComponents/ImportComponents.kt | 23 +- .../ui/widget/components/list/ListScaffold.kt | 35 +-- .../menuItem/RoundDropdownMenuItem.kt | 3 +- .../widget/components/rules/RuleEditSheet.kt | 14 +- .../components/rules/RuleListScaffold.kt | 42 ++- .../settingItem/ClickableSettingItem.kt | 46 ++-- .../settingItem/CompactSettingItems.kt | 4 +- .../settingItem/InputSettingItem.kt | 141 +++++++--- .../components/settingItem/ListSettingItem.kt | 89 ++++-- .../components/settingItem/SettingItem.kt | 19 +- .../settingItem/SliderSettingItem.kt | 253 +++++++++++++----- .../settingItem/SwitchSettingItem.kt | 55 +++- .../components/tabRow/AdaptiveTabRow.kt | 63 +++++ .../app/ui/widget/components/text/AppText.kt | 150 +++++++++++ .../ui/widget/components/title/SmallTitle.kt | 33 +++ .../components/topbar/DynamicTopAppBar.kt | 159 +++++------ .../topbar/GlassMediumFlexibleTopAppBar.kt | 178 ++++++++++++ .../components/topbar/MiuixScrollBehavior.kt | 36 +++ app/version.properties | 4 +- gradle/libs.versions.toml | 22 +- 106 files changed, 2889 insertions(+), 1524 deletions(-) create mode 100644 app/src/main/java/io/legado/app/ui/theme/AdaptivePadding.kt create mode 100644 app/src/main/java/io/legado/app/ui/theme/LegadoTheme.kt create mode 100644 app/src/main/java/io/legado/app/ui/theme/Typography.kt create mode 100644 app/src/main/java/io/legado/app/ui/theme/hazeStyle/HazeLegado.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/AppFloatingActionButton.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/AppNavigationBar.kt delete mode 100644 app/src/main/java/io/legado/app/ui/widget/components/GlassMediumFlexibleTopAppBar.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/button/MiuixBackButton.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/card/SettingCard.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/icon/AppIcon.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/tabRow/AdaptiveTabRow.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/text/AppText.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/title/SmallTitle.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/topbar/GlassMediumFlexibleTopAppBar.kt create mode 100644 app/src/main/java/io/legado/app/ui/widget/components/topbar/MiuixScrollBehavior.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cb9419239..3bee712c9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -286,4 +286,9 @@ dependencies { implementation(libs.material.kolor) implementation(libs.haze.core) implementation(libs.haze.materials) + implementation(libs.miuix) + implementation(libs.miuix.icons) + implementation(libs.capsule) + implementation(libs.backdrop) + implementation(libs.timber) } diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt index 00cff7098..7a3179040 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt @@ -82,6 +82,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -113,6 +114,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -141,6 +143,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -169,6 +172,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -202,6 +206,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -236,6 +241,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -265,6 +271,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -293,6 +300,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -321,6 +329,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -350,6 +359,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -378,6 +388,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -406,6 +417,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -434,6 +446,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, @@ -462,6 +475,7 @@ interface BookDao { durChapterPos, latestChapterTitle, latestChapterTime, + lastCheckCount, totalChapterNum, durChapterIndex, type, diff --git a/app/src/main/java/io/legado/app/ui/about/AboutScreen.kt b/app/src/main/java/io/legado/app/ui/about/AboutScreen.kt index 51b148e92..59f0f1bb7 100644 --- a/app/src/main/java/io/legado/app/ui/about/AboutScreen.kt +++ b/app/src/main/java/io/legado/app/ui/about/AboutScreen.kt @@ -15,9 +15,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme.colorScheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -31,13 +29,15 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.legado.app.R import io.legado.app.constant.AppConst.appInfo +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.settingItem.SettingItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -59,7 +59,7 @@ fun AboutScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(stringResource(R.string.about)) }, + title = stringResource(R.string.about), navigationIcon = { TopbarNavigationButton(onClick = onBack) }, @@ -81,9 +81,9 @@ fun AboutScreen( .width(160.dp) .align(Alignment.CenterHorizontally) ) - Text( + AppText( text = stringResource(R.string.app_name), - style = MaterialTheme.typography.bodyLarge, + style = LegadoTheme.typography.bodyLarge, fontSize = 18.sp, fontWeight = FontWeight.Bold, modifier = Modifier @@ -98,9 +98,9 @@ fun AboutScreen( .fillMaxWidth() .wrapContentWidth(Alignment.CenterHorizontally) .padding(vertical = 4.dp)) - Text( + AppText( text = stringResource(R.string.about_description), - style = MaterialTheme.typography.bodyLarge, + style = LegadoTheme.typography.bodyLarge, fontSize = 12.sp, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/io/legado/app/ui/about/AppLogSheet.kt b/app/src/main/java/io/legado/app/ui/about/AppLogSheet.kt index 2e727ae07..ba3706e15 100644 --- a/app/src/main/java/io/legado/app/ui/about/AppLogSheet.kt +++ b/app/src/main/java/io/legado/app/ui/about/AppLogSheet.kt @@ -18,7 +18,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -31,7 +30,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.constant.AppLog +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.LogUtils import java.util.Date @@ -52,9 +53,9 @@ fun AppLogSheet( .padding(horizontal = 16.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically ) { - Text( + AppText( text = stringResource(R.string.log), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.weight(1f) ) IconButton(onClick = { @@ -82,17 +83,17 @@ fun AppLogSheet( showStackTrace?.let { stackTrace -> AlertDialog( onDismissRequest = { showStackTrace = null }, - title = { Text("Log") }, + title = { AppText("Log") }, text = { SelectionContainer { Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - Text(text = stackTrace, style = MaterialTheme.typography.bodySmall) + AppText(text = stackTrace, style = LegadoTheme.typography.bodySmall) } } }, confirmButton = { TextButton(onClick = { showStackTrace = null }) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } } ) @@ -110,14 +111,14 @@ private fun LogItem( .clickable(onClick = onClick) .padding(16.dp) ) { - Text( + AppText( text = LogUtils.logTimeFormat.format(Date(item.first)), - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, color = MaterialTheme.colorScheme.outline ) - Text( + AppText( text = item.second, - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, modifier = Modifier.padding(top = 4.dp) ) } diff --git a/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkScreen.kt b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkScreen.kt index ed2f086dd..025d24f01 100644 --- a/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkScreen.kt @@ -26,7 +26,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -41,8 +40,6 @@ import io.legado.app.data.entities.Bookmark import io.legado.app.ui.widget.CollapsibleHeader import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.EmptyMessageView -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SearchBarSection import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet import io.legado.app.ui.widget.components.bookmark.BookmarkItem @@ -51,6 +48,9 @@ import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn import io.legado.app.ui.widget.components.lazylist.Scroller import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class, @@ -98,11 +98,7 @@ fun AllBookmarkScreen( topBar = { Column { GlassMediumFlexibleTopAppBar( - title = { - Text( - text = "所有书签" - ) - }, + title = "所有书签", scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBack) @@ -132,7 +128,7 @@ fun AllBookmarkScreen( onDismissRequest = { showMenu = false } ) { RoundDropdownMenuItem( - text = { Text("导出 JSON") }, + text = { AppText("导出 JSON") }, onClick = { showMenu = false pendingExportIsMd = false @@ -140,7 +136,7 @@ fun AllBookmarkScreen( } ) RoundDropdownMenuItem( - text = { Text("导出 Markdown") }, + text = { AppText("导出 Markdown") }, onClick = { showMenu = false pendingExportIsMd = true diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt index 2f5c164d5..12706b01c 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt @@ -52,7 +52,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Slider import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState @@ -79,12 +78,10 @@ import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.rule.ExploreKind import io.legado.app.model.BookShelfState +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.responsiveHazeEffect import io.legado.app.ui.theme.responsiveHazeSource -import io.legado.app.ui.widget.components.AnimatedTextLine import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SearchBarSection import io.legado.app.ui.widget.components.button.AnimatedTextButton import io.legado.app.ui.widget.components.button.TopBarActionButton @@ -94,6 +91,9 @@ import io.legado.app.ui.widget.components.cover.Cover import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import org.koin.androidx.compose.koinViewModel @@ -194,16 +194,16 @@ fun ExploreShowScreen( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { - Text( + AppText( text = "布局列数", - style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold) + style = LegadoTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold) ) Spacer(modifier = Modifier.width(12.dp)) TextCard( text = "$gridColumnCount 列", - textStyle = MaterialTheme.typography.titleSmall, + textStyle = LegadoTheme.typography.titleSmall, verticalPadding = 4.dp, horizontalPadding = 12.dp, cornerRadius = 12.dp @@ -229,7 +229,7 @@ fun ExploreShowScreen( .fillMaxWidth() .padding(horizontal = 16.dp) ) { - Text("完成") + AppText("完成") } } } @@ -294,13 +294,7 @@ fun ExploreShowScreen( modifier = Modifier.responsiveHazeEffect( state = hazeState ), - title = { - AnimatedTextLine( - selectedTitle ?: title, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - }, + title = selectedTitle ?: title, colors = GlassTopAppBarDefaults.glassColors(), navigationIcon = { TopbarNavigationButton(onClick = onBack) @@ -346,7 +340,7 @@ fun ExploreShowScreen( onDismissRequest = { showMenu = false } ) { RoundDropdownMenuItem( - text = { Text("全部显示") }, + text = { AppText("全部显示") }, onClick = { viewModel.setFilterState(BookFilterState.SHOW_ALL) showMenu = false @@ -358,7 +352,7 @@ fun ExploreShowScreen( ) RoundDropdownMenuItem( - text = { Text("隐藏已在书架的同源书籍") }, + text = { AppText("隐藏已在书架的同源书籍") }, onClick = { viewModel.setFilterState(BookFilterState.HIDE_IN_SHELF) showMenu = false @@ -370,7 +364,7 @@ fun ExploreShowScreen( ) RoundDropdownMenuItem( - text = { Text("隐藏已在书架的非同源书籍") }, + text = { AppText("隐藏已在书架的非同源书籍") }, onClick = { viewModel.setFilterState(BookFilterState.HIDE_SAME_NAME_AUTHOR) showMenu = false @@ -382,7 +376,7 @@ fun ExploreShowScreen( ) RoundDropdownMenuItem( - text = { Text("只显示不在书架的书籍") }, + text = { AppText("只显示不在书架的书籍") }, onClick = { viewModel.setFilterState(BookFilterState.SHOW_NOT_IN_SHELF_ONLY) showMenu = false @@ -509,7 +503,7 @@ fun KindGridItem( enabled = isClickable, selected = isSelected, label = { - Text( + AppText( text = kind.title, fontSize = 12.sp, modifier = Modifier.fillMaxWidth(), @@ -576,32 +570,32 @@ fun ExploreBookItem( .weight(1f) .align(Alignment.CenterVertically)) { - Text( + AppText( text = book.name, - style = MaterialTheme.typography.titleSmall, + style = LegadoTheme.typography.titleSmall, maxLines = 1, overflow = TextOverflow.Ellipsis ) Row { - Text( + AppText( text = book.author, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1 ) val latestChapter = book.latestChapterTitle if (!latestChapter.isNullOrEmpty()) { - Text( + AppText( text = " • ", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = Color.Gray, maxLines = 1 ) - Text( + AppText( text = "最新: $latestChapter", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -612,9 +606,9 @@ fun ExploreBookItem( val intro = book.intro?.replace("\\s+".toRegex(), "") ?: "" if (intro.isNotEmpty()) { - Text( + AppText( text = intro, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, color = Color.Gray, maxLines = 2, minLines = 2, @@ -654,9 +648,12 @@ fun ExploreBookGridItem( val content: (@Composable RowScope.() -> Unit)? = if (!badgeText.isNullOrBlank()) { { - Text( + AppText( text = badgeText, - style = MaterialTheme.typography.labelSmall.copy(fontWeight = FontWeight.Bold, fontSize = 9.sp) + style = LegadoTheme.typography.labelSmall.copy( + fontWeight = FontWeight.Bold, + fontSize = 9.sp + ) ) } } else { @@ -681,9 +678,9 @@ fun ExploreBookGridItem( Spacer(modifier = Modifier.height(4.dp)) - Text( + AppText( text = book.name, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, fontWeight = FontWeight.Bold, maxLines = 2, overflow = TextOverflow.Ellipsis @@ -698,10 +695,10 @@ fun TagChip(text: String) { color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f), shape = RoundedCornerShape(4.dp) ) { - Text( + AppText( text = text, modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp), - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, color = MaterialTheme.colorScheme.primary ) } @@ -742,13 +739,13 @@ fun LoadMoreFooter( }, label = "FooterTextChange" ) { text -> - Text( + AppText( text = text, color = when { errorMsg != null -> Color.Red else -> Color.Gray }, - style = MaterialTheme.typography.bodySmall + style = LegadoTheme.typography.bodySmall ) } diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt index c22a618c3..472ce06ee 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt @@ -18,11 +18,9 @@ import androidx.compose.material.icons.filled.Restore import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedIconButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -38,10 +36,12 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.data.entities.BookGroup import io.legado.app.lib.dialogs.alert +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.cover.Cover import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.FileUtils import io.legado.app.utils.MD5Utils import io.legado.app.utils.SelectImageContract @@ -113,9 +113,9 @@ fun GroupEditContent( .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally ) { - Text( + AppText( text = stringResource(R.string.group_edit), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(vertical = 16.dp) ) @@ -138,7 +138,7 @@ fun GroupEditContent( OutlinedTextField( value = groupName, onValueChange = { groupName = it }, - label = { Text(stringResource(R.string.group_name)) }, + label = { AppText(stringResource(R.string.group_name)) }, modifier = Modifier.fillMaxWidth(), singleLine = true ) @@ -206,7 +206,7 @@ fun GroupEditContent( Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { OutlinedButton(onClick = onDismissRequest) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } Button(onClick = { if (groupName.isEmpty()) { @@ -235,7 +235,7 @@ fun GroupEditContent( } } }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookScreen.kt b/app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookScreen.kt index 756d2d97a..3f0588aee 100644 --- a/app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookScreen.kt @@ -51,7 +51,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.RadioButton -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState @@ -80,6 +79,7 @@ import io.legado.app.data.entities.Book import io.legado.app.data.entities.Server import io.legado.app.help.config.AppConfig import io.legado.app.model.remote.RemoteBook +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.EmptyMessageView import io.legado.app.ui.widget.components.SelectionActions @@ -89,6 +89,7 @@ import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.ArchiveUtils import io.legado.app.utils.ConvertUtils import io.legado.app.utils.FileDoc @@ -157,19 +158,19 @@ fun RemoteBookScreen( is RemoteBookDialog.DownloadArchive -> { AlertDialog( onDismissRequest = { dialogState = null }, - title = { Text(stringResource(R.string.draw)) }, - text = { Text(stringResource(R.string.archive_not_found)) }, + title = { AppText(stringResource(R.string.draw)) }, + text = { AppText(stringResource(R.string.archive_not_found)) }, confirmButton = { OutlinedButton(onClick = { scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) } dialogState = null }) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = { dialogState = null }) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) @@ -178,19 +179,19 @@ fun RemoteBookScreen( is RemoteBookDialog.ReImport -> { AlertDialog( onDismissRequest = { dialogState = null }, - title = { Text("是否重新加入书架?") }, - text = { Text("将会覆盖书籍") }, + title = { AppText("是否重新加入书架?") }, + text = { AppText("将会覆盖书籍") }, confirmButton = { OutlinedButton(onClick = { scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) } dialogState = null }) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = { dialogState = null }) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) @@ -259,7 +260,7 @@ fun RemoteBookScreen( }, dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( - text = { Text("按名称排序") }, + text = { AppText("按名称排序") }, onClick = { viewModel.toggleSort(RemoteBookSort.Name) dismiss() @@ -271,7 +272,7 @@ fun RemoteBookScreen( } ) RoundDropdownMenuItem( - text = { Text("按时间排序") }, + text = { AppText("按时间排序") }, onClick = { viewModel.toggleSort(RemoteBookSort.Default) dismiss() @@ -381,9 +382,9 @@ private fun ServersSheetContent( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - Text( + AppText( text = stringResource(R.string.server_config), - style = MaterialTheme.typography.titleLarge + style = LegadoTheme.typography.titleLarge ) IconButton(onClick = onAdd) { Icon(Icons.Default.Add, contentDescription = "添加") @@ -447,9 +448,9 @@ private fun ServerItem( ListItem( modifier = Modifier.animateContentSize(), headlineContent = { - Text( + AppText( text = name, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -462,9 +463,9 @@ private fun ServerItem( }, supportingContent = url?.let { { - Text( + AppText( text = it, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -514,16 +515,16 @@ private fun ServerConfigSheetContent( .padding(16.dp) .verticalScroll(rememberScrollState()) ) { - Text( + AppText( text = if (server == null) "添加服务器" else "编辑服务器", - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(bottom = 16.dp) ) OutlinedTextField( value = name, onValueChange = { name = it }, - label = { Text("名称") }, + label = { AppText("名称") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) @@ -531,7 +532,7 @@ private fun ServerConfigSheetContent( OutlinedTextField( value = url, onValueChange = { url = it }, - label = { Text("URL") }, + label = { AppText("URL") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) @@ -539,7 +540,7 @@ private fun ServerConfigSheetContent( OutlinedTextField( value = username, onValueChange = { username = it }, - label = { Text("用户名") }, + label = { AppText("用户名") }, modifier = Modifier.fillMaxWidth(), singleLine = true ) @@ -547,7 +548,7 @@ private fun ServerConfigSheetContent( OutlinedTextField( value = password, onValueChange = { password = it }, - label = { Text("密码") }, + label = { AppText("密码") }, modifier = Modifier.fillMaxWidth(), singleLine = true, visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), @@ -571,7 +572,7 @@ private fun ServerConfigSheetContent( onClick = onCancel, modifier = Modifier.weight(1f) ) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } Button( onClick = { @@ -587,7 +588,7 @@ private fun ServerConfigSheetContent( modifier = Modifier.weight(1f), enabled = name.isNotBlank() && url.isNotBlank() ) { - Text("保存") + AppText("保存") } } } @@ -625,9 +626,9 @@ private fun PathNavigationBar( itemsIndexed(pathNames) { index, name -> val isLast = index == pathNames.lastIndex - Text( + AppText( text = name, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, fontWeight = if (isLast) FontWeight.SemiBold else FontWeight.Medium, color = if (isLast) MaterialTheme.colorScheme.primary @@ -716,9 +717,9 @@ private fun RemoteBookItem( modifier = Modifier.weight(1f) ) { - Text( + AppText( text = book.filename.substringBeforeLast("."), - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -732,7 +733,7 @@ private fun RemoteBookItem( if (book.contentType.isNotEmpty()) { TextCard( text = book.contentType.uppercase(), - textStyle = MaterialTheme.typography.labelSmall, + textStyle = LegadoTheme.typography.labelSmall, horizontalPadding = 4.dp, verticalPadding = 2.dp, cornerRadius = 4.dp, @@ -743,11 +744,11 @@ private fun RemoteBookItem( Spacer(modifier = Modifier.width(6.dp)) } - Text( + AppText( text = "${ConvertUtils.formatFileSize(book.size)} • ${ AppConst.dateFormat.format(book.lastModify) }", - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) } diff --git a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt index f84aea298..d7798d3c0 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -47,12 +46,13 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.ui.book.changecover.ChangeCoverDialog import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.button.TopBarButtonVariant import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.cover.Cover import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.SelectImageContract import io.legado.app.utils.launch import io.legado.app.utils.showDialogFragment @@ -71,7 +71,7 @@ fun BookInfoEditScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(text = stringResource(id = R.string.book_info_edit)) }, + title = stringResource(id = R.string.book_info_edit), navigationIcon = { TopbarNavigationButton( onClick = onBack, @@ -191,35 +191,35 @@ fun BookInfoEditContent( OutlinedTextField( value = uiState.name, onValueChange = { viewModel.onNameChange(it) }, - label = { Text("书名") }, + label = { AppText("书名") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = uiState.author, onValueChange = { viewModel.onAuthorChange(it) }, - label = { Text("作者") }, + label = { AppText("作者") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = uiState.coverUrl ?: "", onValueChange = { viewModel.onCoverUrlChange(it) }, - label = { Text("封面链接") }, + label = { AppText("封面链接") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = uiState.intro ?: "", onValueChange = { viewModel.onIntroChange(it) }, - label = { Text("简介") }, + label = { AppText("简介") }, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( value = uiState.remark ?: "", onValueChange = { viewModel.onRemarkChange(it) }, - label = { Text("备注") }, + label = { AppText("备注") }, modifier = Modifier.fillMaxWidth() ) } @@ -251,7 +251,7 @@ fun BookTypeDropdown( state = textFieldState, readOnly = true, lineLimits = TextFieldLineLimits.SingleLine, - label = { Text("书籍类型") }, + label = { AppText("书籍类型") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, @@ -269,7 +269,7 @@ fun BookTypeDropdown( ) { bookTypes.forEach { option -> DropdownMenuItem( - text = { Text(option) }, + text = { AppText(option) }, onClick = { onTypeSelected(option) expanded = false diff --git a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt index e2fec7f18..3263ec78d 100644 --- a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt @@ -43,7 +43,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -78,11 +77,10 @@ import androidx.compose.ui.zIndex import cn.hutool.core.date.DateUtil import io.legado.app.data.entities.readRecord.ReadRecord import io.legado.app.data.entities.readRecord.ReadRecordDetail +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AnimatedTextLine import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.EmptyMessageView -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SearchBarSection import io.legado.app.ui.widget.components.SectionHeader import io.legado.app.ui.widget.components.button.AlertButton @@ -101,6 +99,9 @@ import io.legado.app.ui.widget.components.heatmap.rememberWeeks import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet import io.legado.app.ui.widget.components.swipe.SwipeAction import io.legado.app.ui.widget.components.swipe.SwipeActionContainer +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.StringUtils.formatFriendlyDate import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel @@ -148,11 +149,7 @@ fun ReadRecordScreen( topBar = { Column { GlassMediumFlexibleTopAppBar( - title = { - Text( - text = "阅读记录" - ) - }, + title = "阅读记录", subtitle = { val subTitle = when (displayMode) { DisplayMode.AGGREGATE -> "汇总视图" @@ -271,10 +268,10 @@ fun ReadRecordScreen( onDismissRequest = { pendingDeleteAction = null }, - title = { Text("确认删除") }, + title = { AppText("确认删除") }, text = { Column { - Text("确定要删除这条记录吗?") + AppText("确定要删除这条记录吗?") Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier @@ -289,10 +286,10 @@ fun ReadRecordScreen( verticalAlignment = Alignment.CenterVertically ) { Checkbox(checked = skipDeleteConfirmTemp, onCheckedChange = null) - Text( + AppText( text = "不再提示", modifier = Modifier.padding(start = 8.dp), - style = MaterialTheme.typography.bodyMedium + style = LegadoTheme.typography.bodyMedium ) } } @@ -311,7 +308,7 @@ fun ReadRecordScreen( TextButton(onClick = { pendingDeleteAction = null }) { - Text("取消") + AppText("取消") } } ) @@ -346,10 +343,10 @@ fun ReadRecordScreen( AlertDialog( onDismissRequest = { mergeDialogData = null }, - title = { Text("合并阅读记录") }, + title = { AppText("合并阅读记录") }, text = { Column { - Text("将以下作者的“${targetRecord.bookName}”合并到 ${targetRecord.bookAuthor.ifBlank { "未知作者" }}") + AppText("将以下作者的“${targetRecord.bookName}”合并到 ${targetRecord.bookAuthor.ifBlank { "未知作者" }}") Spacer(modifier = Modifier.height(8.dp)) candidates.forEach { candidate -> @@ -367,10 +364,10 @@ fun ReadRecordScreen( verticalAlignment = Alignment.CenterVertically ) { Checkbox(checked = isChecked, onCheckedChange = null) - Text( + AppText( text = "$author(${formatDuring(candidate.readTime)})", modifier = Modifier.padding(start = 8.dp), - style = MaterialTheme.typography.bodyMedium + style = LegadoTheme.typography.bodyMedium ) } } @@ -386,12 +383,12 @@ fun ReadRecordScreen( mergeDialogData = null } ) { - Text("合并") + AppText("合并") } }, dismissButton = { TextButton(onClick = { mergeDialogData = null }) { - Text("取消") + AppText("取消") } } ) @@ -686,21 +683,21 @@ fun LatestReadItem( Spacer(modifier = Modifier.width(16.dp)) Column(modifier = Modifier.weight(1f)) { - Text( + AppText( text = record.bookName, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Text( + AppText( text = record.bookAuthor.ifBlank { "未知作者" }, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline, maxLines = 1, overflow = TextOverflow.Ellipsis ) Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( modifier = Modifier .basicMarquee( iterations = Int.MAX_VALUE, @@ -716,7 +713,7 @@ fun LatestReadItem( append("${DateUtil.format(Date(record.lastRead), "yyyy-MM-dd HH:mm")}") } }, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -783,9 +780,9 @@ fun TimelineSessionItem( modifier = Modifier.width(48.dp), verticalArrangement = Arrangement.Center ) { - Text( + AppText( text = endTimeText, - style = MaterialTheme.typography.bodySmall + style = LegadoTheme.typography.bodySmall ) } @@ -795,23 +792,23 @@ fun TimelineSessionItem( Cover(coverPath) Spacer(modifier = Modifier.width(8.dp)) Column { - Text( + AppText( text = session.bookName, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Text( + AppText( text = session.bookAuthor.ifBlank { "未知作者" }, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline, maxLines = 1, overflow = TextOverflow.Ellipsis ) Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = chapterTitle.orEmpty(), - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, color = MaterialTheme.colorScheme.outline, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -847,21 +844,21 @@ fun ReadRecordItem( Spacer(modifier = Modifier.width(16.dp)) Column(modifier = Modifier.weight(1f)) { - Text( + AppText( text = detail.bookName, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, maxLines = 1 ) - Text( + AppText( text = detail.bookAuthor.ifBlank { "未知作者" }, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline, ) Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = "阅读时长: ${formatDuring(detail.readTime)}", color = MaterialTheme.colorScheme.outline, - style = MaterialTheme.typography.labelSmall + style = LegadoTheme.typography.labelSmall ) } } @@ -876,17 +873,17 @@ fun DateHeader( SectionHeader( titleContent = { Column { - Text( + AppText( text = dateText, - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.secondary ) dailyTotalTime?.let { total -> - Text( + AppText( text = "已读 ${formatDuring(total)}", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurface ) } @@ -934,28 +931,28 @@ fun ReadingSummaryCard( Column(modifier = Modifier.weight(1f)) { - Text( + AppText( text = title, - style = MaterialTheme.typography.labelLarge, + style = LegadoTheme.typography.labelLarge, color = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.height(4.dp)) Row(verticalAlignment = Alignment.Bottom) { - Text( + AppText( text = "已读 ", - style = MaterialTheme.typography.titleMedium + style = LegadoTheme.typography.titleMedium ) - Text( + AppText( text = "$bookCount", - style = MaterialTheme.typography.headlineMedium, + style = LegadoTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold, ) - Text( + AppText( text = " 本书", - style = MaterialTheme.typography.titleMedium + style = LegadoTheme.typography.titleMedium ) } @@ -965,9 +962,9 @@ fun ReadingSummaryCard( val minutes = totalDurationMinutes % 60 val timeString = if (hours > 0) "${hours}小时${minutes}分钟" else "${minutes}分钟" - Text( + AppText( text = "共阅读 $timeString", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentScreen.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentScreen.kt index 948144d6d..813129e82 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentScreen.kt @@ -44,7 +44,6 @@ import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.PlainTooltip -import androidx.compose.material3.Text import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox import androidx.compose.material3.TooltipDefaults @@ -64,11 +63,9 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.legado.app.data.entities.SearchContentHistory -import io.legado.app.ui.widget.components.AnimatedText +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.EmptyMessageView -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SearchBarSection import io.legado.app.ui.widget.components.button.SmallAnimatedActionButton import io.legado.app.ui.widget.components.button.SmallIconButton @@ -76,6 +73,9 @@ import io.legado.app.ui.widget.components.button.TopBarAnimatedActionButton import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel @@ -140,12 +140,9 @@ fun SearchContentScreen( topBar = { Column { GlassMediumFlexibleTopAppBar( - title = { - val title = if (searchQuery.isNotBlank() && searchResults.isNotEmpty()) { - "共 ${searchResults.size} 条结果" - } else "搜索内容" - AnimatedText(text = title) - }, + title = if (searchQuery.isNotBlank() && searchResults.isNotEmpty()) { + "共 ${searchResults.size} 条结果" + } else "搜索内容", navigationIcon = { TopbarNavigationButton(onClick = onBack) }, actions = { Row( @@ -191,7 +188,7 @@ fun SearchContentScreen( ), tooltip = { PlainTooltip { - Text(if (isSearching) "停止搜索" else "跳转到当前章节") + AppText(if (isSearching) "停止搜索" else "跳转到当前章节") } }, state = rememberTooltipState(), @@ -310,9 +307,9 @@ fun SearchHistoryList( .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp) ) { - Text( + AppText( text = "搜索历史", - style = MaterialTheme.typography.titleSmallEmphasized, + style = LegadoTheme.typography.titleSmallEmphasized, color = MaterialTheme.colorScheme.primary, modifier = Modifier.align(Alignment.Center) ) @@ -342,7 +339,7 @@ fun SearchHistoryList( .clickable { onHistoryClick(item) } .animateItem(), headlineContent = { - Text( + AppText( text = item.query, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -378,7 +375,7 @@ fun SearchHistoryList( modifier = Modifier.size(18.dp) ) Spacer(Modifier.width(8.dp)) - Text("清除搜索历史") + AppText("清除搜索历史") } } } @@ -407,7 +404,7 @@ fun SearchResultItem( Box(modifier = Modifier.padding(16.dp)) { Column { - Text( + AppText( text = buildAnnotatedString { append( result.getTitleSpannable( @@ -415,14 +412,14 @@ fun SearchResultItem( ) ) }, - style = MaterialTheme.typography.titleSmall + style = LegadoTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(8.dp)) HorizontalDivider() Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = buildAnnotatedString { append( result.getContentSpannable( @@ -432,7 +429,7 @@ fun SearchResultItem( ) ) }, - style = MaterialTheme.typography.bodyMedium + style = LegadoTheme.typography.bodyMedium ) } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt b/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt index 09c46d2bd..b1ede3b7d 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt @@ -63,7 +63,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.PrimaryScrollableTabRow import androidx.compose.material3.Surface import androidx.compose.material3.Tab -import androidx.compose.material3.Text import androidx.compose.material3.ToggleFloatingActionButton import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon import androidx.compose.material3.animateFloatingActionButton @@ -95,11 +94,11 @@ import io.legado.app.data.entities.Bookmark import io.legado.app.help.book.isLocal import io.legado.app.ui.book.toc.rule.TxtTocRuleActivity import io.legado.app.ui.replace.ReplaceEditRoute +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.CollapsibleHeader import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.EmptyMessageView -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SelectionBottomBar import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet import io.legado.app.ui.widget.components.bookmark.BookmarkItem @@ -109,7 +108,9 @@ import io.legado.app.ui.widget.components.divider.PillHeaderDivider import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.topbar.DynamicTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel @@ -312,33 +313,33 @@ fun TocScreen( when (pagerState.currentPage) { 0 -> { RoundDropdownMenuItem( - text = { Text("使用替换规则") }, + text = { AppText("使用替换规则") }, trailingIcon = { Checkbox(checked = useReplace, onCheckedChange = null) }, onClick = { viewModel.toggleUseReplace() } ) RoundDropdownMenuItem( - text = { Text("显示字数") }, + text = { AppText("显示字数") }, trailingIcon = { Checkbox(checked = showWordCount, onCheckedChange = null) }, onClick = { viewModel.toggleShowWordCount() } ) RoundDropdownMenuItem( - text = { Text("反转目录") }, + text = { AppText("反转目录") }, onClick = { viewModel.reverseToc() } ) PillDivider() RoundDropdownMenuItem( - text = { Text("替换规则") }, + text = { AppText("替换规则") }, onClick = { onOpenReplaceRule(null) dismiss() } ) RoundDropdownMenuItem( - text = { Text("新建替换规则") }, + text = { AppText("新建替换规则") }, onClick = { val scopes = mutableListOf() book?.name?.let { scopes.add(it) } @@ -358,7 +359,7 @@ fun TocScreen( if (book?.isLocal == true) { PillHeaderDivider(title = "本地书籍选项") RoundDropdownMenuItem( - text = { Text("本地书籍目录规则") }, + text = { AppText("本地书籍目录规则") }, onClick = { val intent = Intent(context, TxtTocRuleActivity::class.java).apply { @@ -369,7 +370,7 @@ fun TocScreen( } ) RoundDropdownMenuItem( - text = { Text("拆分超长章节") }, + text = { AppText("拆分超长章节") }, trailingIcon = { Checkbox( checked = viewModel.isSplitLongChapter, @@ -386,7 +387,7 @@ fun TocScreen( else -> { RoundDropdownMenuItem( - text = { Text("导出书签为JSON") }, + text = { AppText("导出书签为JSON") }, onClick = { val dateFormat = SimpleDateFormat( "yyyyMMdd_HHmm", @@ -398,7 +399,7 @@ fun TocScreen( } ) RoundDropdownMenuItem( - text = { Text("导出书签为MarkDown") }, + text = { AppText("导出书签为MarkDown") }, onClick = { val dateFormat = SimpleDateFormat( "yyyyMMdd_HHmm", @@ -428,7 +429,7 @@ fun TocScreen( selected = pagerState.currentPage == 0, onClick = { scope.launch { pagerState.animateScrollToPage(0) } }, text = { - Text( + AppText( text = "目录", modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.onSurfaceVariant @@ -439,7 +440,7 @@ fun TocScreen( selected = pagerState.currentPage == 1, onClick = { scope.launch { pagerState.animateScrollToPage(1) } }, text = { - Text( + AppText( text = "书签", modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.onSurfaceVariant @@ -464,13 +465,13 @@ fun TocScreen( onDismissRequest = { showVolumeMenu = false } ) { RoundDropdownMenuItem( - text = { Text("展开所有卷") }, + text = { AppText("展开所有卷") }, onClick = { viewModel.expandAllVolumes(); showVolumeMenu = false } ) RoundDropdownMenuItem( - text = { Text("收起所有卷") }, + text = { AppText("收起所有卷") }, onClick = { viewModel.collapseAllVolumes(); showVolumeMenu = false } @@ -482,7 +483,7 @@ fun TocScreen( PillHeaderDivider(title = "快速跳转") volumeItems.forEach { uiItem -> RoundDropdownMenuItem( - text = { Text(uiItem.title) }, + text = { AppText(uiItem.title) }, onClick = { scope.launch { val targetIndex = @@ -541,7 +542,7 @@ fun TocScreen( fabMenuExpanded = false }, icon = { Icon(icon, contentDescription = null) }, - text = { Text(text = label) } + text = { AppText(text = label) } ) } } @@ -729,9 +730,9 @@ fun ChapterItem( ) } - Text( + AppText( text = item.title, - style = MaterialTheme.typography.bodyMediumEmphasized.copy(fontWeight = FontWeight.Medium), + style = LegadoTheme.typography.bodyMediumEmphasized.copy(fontWeight = FontWeight.Medium), color = textColor, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -739,9 +740,9 @@ fun ChapterItem( } if (!item.tag.isNullOrEmpty()) { - Text( + AppText( text = item.tag, - style = MaterialTheme.typography.labelSmallEmphasized, + style = LegadoTheme.typography.labelSmallEmphasized, color = detailColor.copy(alpha = 0.8f), maxLines = 1, overflow = TextOverflow.Ellipsis @@ -910,11 +911,11 @@ private fun StatusIcon( color = Color.Transparent ) { if (wordCount != null) { - Text( + AppText( modifier = Modifier .padding(horizontal = 8.dp, vertical = 4.dp), text = wordCount, - style = MaterialTheme.typography.labelSmall.copy(fontSize = 9.sp), + style = LegadoTheme.typography.labelSmall.copy(fontSize = 9.sp), color = MaterialTheme.colorScheme.onSurfaceVariant ) } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtRuleScreen.kt b/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtRuleScreen.kt index 30738041b..dd17674c4 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtRuleScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtRuleScreen.kt @@ -19,11 +19,9 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -46,6 +44,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.base.BaseRuleEvent import io.legado.app.data.entities.TxtTocRule +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.DraggableSelectionHandler import io.legado.app.ui.widget.components.button.SmallIconButton @@ -59,6 +58,7 @@ import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleEditFields import io.legado.app.ui.widget.components.rules.RuleEditSheet import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.text.AppText import org.koin.androidx.compose.koinViewModel import sh.calvin.reorderable.rememberReorderableLazyListState @@ -196,8 +196,8 @@ fun TxtRuleScreen( onConfirm = { viewModel.saveImportedRules() }, itemContent = { rule, _ -> Column { - Text(rule.name, style = MaterialTheme.typography.titleMedium) - Text(rule.rule, style = MaterialTheme.typography.bodySmall, maxLines = 1) + AppText(rule.name, style = LegadoTheme.typography.titleMedium) + AppText(rule.rule, style = LegadoTheme.typography.bodySmall, maxLines = 1) } } ) @@ -212,16 +212,16 @@ fun TxtRuleScreen( showDeleteRuleDialog?.let { rule -> AlertDialog( onDismissRequest = { showDeleteRuleDialog = null }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.del_msg)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.del_msg)) }, confirmButton = { OutlinedButton(onClick = { viewModel.delete(rule); showDeleteRuleDialog = null - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showDeleteRuleDialog = null }) { - Text( + AppText( stringResource(R.string.cancel) ) } @@ -312,7 +312,7 @@ fun TxtRuleScreen( snackbarHostState = snackbarHostState, dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_str)) }, + text = { AppText(stringResource(R.string.import_str)) }, onClick = { showImportSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.FileOpen, null) } ) diff --git a/app/src/main/java/io/legado/app/ui/config/ConfigNavScreen.kt b/app/src/main/java/io/legado/app/ui/config/ConfigNavScreen.kt index 89db7857f..4b4b1c099 100644 --- a/app/src/main/java/io/legado/app/ui/config/ConfigNavScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/ConfigNavScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -14,11 +13,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -36,7 +35,7 @@ fun ConfigNavScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(stringResource(R.string.setting)) }, + title = stringResource(R.string.setting), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) diff --git a/app/src/main/java/io/legado/app/ui/config/backupConfig/BackupConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/backupConfig/BackupConfigScreen.kt index ac34f94a4..e261c97d0 100644 --- a/app/src/main/java/io/legado/app/ui/config/backupConfig/BackupConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/backupConfig/BackupConfigScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedButton import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextField import androidx.compose.runtime.Composable @@ -42,14 +41,15 @@ import io.legado.app.help.storage.Restore import io.legado.app.lib.permission.Permissions import io.legado.app.lib.permission.PermissionsCompat import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem import io.legado.app.ui.widget.components.settingItem.InputSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.isContentScheme import io.legado.app.utils.takePersistablePermissionSafely import kotlinx.coroutines.launch @@ -166,9 +166,7 @@ fun BackupConfigScreen( }, topBar = { GlassMediumFlexibleTopAppBar( - title = { - Text(stringResource(R.string.backup_restore)) - }, + title = stringResource(R.string.backup_restore), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) @@ -387,19 +385,19 @@ fun BackupConfigScreen( if (showWebDavAuthDialog) { AlertDialog( onDismissRequest = { showWebDavAuthDialog = false }, - title = { Text(stringResource(R.string.web_dav_account)) }, + title = { AppText(stringResource(R.string.web_dav_account)) }, text = { Column { TextField( value = tempAccount, onValueChange = { tempAccount = it }, - label = { Text("账号") } + label = { AppText("账号") } ) Spacer(modifier = Modifier.padding(8.dp)) TextField( value = tempPassword, onValueChange = { tempPassword = it }, - label = { Text("密码") }, + label = { AppText("密码") }, visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), trailingIcon = { @@ -432,12 +430,12 @@ fun BackupConfigScreen( } } }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showWebDavAuthDialog = false }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -484,7 +482,7 @@ fun BackupConfigScreen( if (showRestoreSheet && backupNames.isNotEmpty()) { AlertDialog( onDismissRequest = { showRestoreSheet = false }, - title = { Text(stringResource(R.string.select_restore_file)) }, + title = { AppText(stringResource(R.string.select_restore_file)) }, text = { Column { backupNames.forEach { name -> @@ -508,7 +506,7 @@ fun BackupConfigScreen( } ) }) { - Text(name) + AppText(name) } } } @@ -516,7 +514,7 @@ fun BackupConfigScreen( confirmButton = {}, dismissButton = { TextButton(onClick = { showRestoreSheet = false }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -535,7 +533,7 @@ fun BackupConfigScreen( io.legado.app.help.storage.BackupConfig.saveIgnoreConfig() showBackupIgnoreDialog = false }, - title = { Text(stringResource(R.string.restore_ignore)) }, + title = { AppText(stringResource(R.string.restore_ignore)) }, text = { Column { io.legado.app.help.storage.BackupConfig.ignoreTitle.forEachIndexed { index, title -> @@ -546,7 +544,7 @@ fun BackupConfigScreen( ] = checkedItems[index] }) { val isChecked = checkedItems[index] - Text(if (isChecked) "✓ $title" else title) + AppText(if (isChecked) "✓ $title" else title) } } } @@ -556,7 +554,7 @@ fun BackupConfigScreen( io.legado.app.help.storage.BackupConfig.saveIgnoreConfig() showBackupIgnoreDialog = false }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { @@ -564,7 +562,7 @@ fun BackupConfigScreen( io.legado.app.help.storage.BackupConfig.saveIgnoreConfig() showBackupIgnoreDialog = false }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -573,7 +571,7 @@ fun BackupConfigScreen( if (showLoadingDialog) { AlertDialog( onDismissRequest = {}, - title = { Text(loadingText) }, + title = { AppText(loadingText) }, confirmButton = {}, dismissButton = {} ) @@ -589,16 +587,16 @@ fun ConfirmDialog( ) { AlertDialog( onDismissRequest = onDismiss, - title = { Text(title) }, - text = { Text(text) }, + title = { AppText(title) }, + text = { AppText(text) }, confirmButton = { OutlinedButton(onClick = onConfirm) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismiss) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverConfigScreen.kt index 5aee17431..829901a72 100644 --- a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverConfigScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api 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 @@ -27,14 +26,14 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.dialog.ColorPickerSheet import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class) @@ -52,7 +51,7 @@ fun CoverConfigScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(stringResource(R.string.cover_config)) }, + title = stringResource(R.string.cover_config), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) diff --git a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverManageSheet.kt b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverManageSheet.kt index 52c6298ca..7f28526ad 100644 --- a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverManageSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverManageSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -36,8 +35,10 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import io.legado.app.R import io.legado.app.constant.PreferKey +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -69,9 +70,9 @@ fun CoverManageSheet( .fillMaxWidth() .padding(bottom = 24.dp) ) { - Text( + AppText( text = stringResource(R.string.default_cover), - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.padding(16.dp) ) diff --git a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt index 974f3f42f..56b5ceb74 100644 --- a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt @@ -11,7 +11,6 @@ import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -25,8 +24,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.model.BookCover +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet import io.legado.app.ui.widget.components.settingItem.InputSettingItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -58,9 +59,9 @@ fun CoverRuleConfigSheet( .fillMaxWidth() .padding(16.dp) ) { - Text( + AppText( text = stringResource(R.string.cover_rule), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(bottom = 16.dp) ) @@ -72,7 +73,7 @@ fun CoverRuleConfigSheet( checked = enable, onCheckedChange = { enable = it } ) - Text(text = stringResource(R.string.enable)) + AppText(text = stringResource(R.string.enable)) } InputSettingItem( @@ -97,13 +98,16 @@ fun CoverRuleConfigSheet( BookCover.delCoverRule() onDismissRequest() }) { - Text(stringResource(R.string.delete), color = MaterialTheme.colorScheme.error) + AppText( + stringResource(R.string.delete), + color = MaterialTheme.colorScheme.error + ) } Spacer(modifier = Modifier.weight(1f)) OutlinedButton(onClick = onDismissRequest) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } Spacer(modifier = Modifier.padding(horizontal = 4.dp)) @@ -118,7 +122,7 @@ fun CoverRuleConfigSheet( onDismissRequest() } }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/CheckSourceBottomSheet.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/CheckSourceBottomSheet.kt index 790e95878..6be30bb24 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/CheckSourceBottomSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/CheckSourceBottomSheet.kt @@ -10,7 +10,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import io.legado.app.ui.widget.components.text.AppText import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -18,6 +18,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.checkBox.CheckboxGroupContainer import io.legado.app.ui.widget.components.checkBox.CheckboxItem import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet @@ -41,9 +42,9 @@ fun CheckSourceBottomSheet( .padding(horizontal = 16.dp) .padding(bottom = 32.dp) ) { - Text( + AppText( text = stringResource(R.string.check_source_config), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(vertical = 16.dp) ) @@ -131,7 +132,7 @@ fun CheckSourceBottomSheet( horizontalArrangement = Arrangement.End ) { TextButton(onClick = onDismiss) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } Button(onClick = { if (viewModel.saveCheckSourceConfig()) { @@ -140,7 +141,7 @@ fun CheckSourceBottomSheet( Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show() } }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/DirectLinkUploadBottomSheet.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/DirectLinkUploadBottomSheet.kt index 7014ae1f5..ac5fdd38c 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/DirectLinkUploadBottomSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/DirectLinkUploadBottomSheet.kt @@ -24,7 +24,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable @@ -41,8 +40,10 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.help.DirectLinkUpload import io.legado.app.lib.dialogs.selector +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.checkBox.CheckboxItem import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject import io.legado.app.utils.getClipText @@ -75,9 +76,9 @@ fun DirectLinkUploadBottomSheet( ) { CenterAlignedTopAppBar( title = { - Text( + AppText( text = stringResource(R.string.direct_link_upload_config), - style = MaterialTheme.typography.titleLarge + style = LegadoTheme.typography.titleLarge ) }, actions = { @@ -89,7 +90,7 @@ fun DirectLinkUploadBottomSheet( onDismissRequest = { showMenu = false } ) { DropdownMenuItem( - text = { Text("导入默认") }, + text = { AppText("导入默认") }, leadingIcon = { Icon(Icons.Default.Download, null) }, onClick = { showMenu = false @@ -99,7 +100,7 @@ fun DirectLinkUploadBottomSheet( } ) DropdownMenuItem( - text = { Text(stringResource(R.string.copy_rule)) }, + text = { AppText(stringResource(R.string.copy_rule)) }, leadingIcon = { Icon(Icons.Default.ContentCopy, null) }, onClick = { showMenu = false @@ -113,7 +114,7 @@ fun DirectLinkUploadBottomSheet( } ) DropdownMenuItem( - text = { Text(stringResource(R.string.paste_rule)) }, + text = { AppText(stringResource(R.string.paste_rule)) }, leadingIcon = { Icon(Icons.Default.ContentPaste, null) }, onClick = { showMenu = false @@ -141,7 +142,7 @@ fun DirectLinkUploadBottomSheet( OutlinedTextField( value = viewModel.uploadUrl, onValueChange = { viewModel.uploadUrl = it }, - label = { Text(stringResource(R.string.upload_url)) }, + label = { AppText(stringResource(R.string.upload_url)) }, modifier = Modifier.fillMaxWidth(), ) @@ -150,7 +151,7 @@ fun DirectLinkUploadBottomSheet( OutlinedTextField( value = viewModel.downloadUrlRule, onValueChange = { viewModel.downloadUrlRule = it }, - label = { Text(stringResource(R.string.download_url_rule)) }, + label = { AppText(stringResource(R.string.download_url_rule)) }, modifier = Modifier.fillMaxWidth(), ) @@ -159,7 +160,7 @@ fun DirectLinkUploadBottomSheet( OutlinedTextField( value = viewModel.summary, onValueChange = { viewModel.summary = it }, - label = { Text(stringResource(R.string.summary)) }, + label = { AppText(stringResource(R.string.summary)) }, modifier = Modifier.fillMaxWidth(), ) @@ -178,11 +179,11 @@ fun DirectLinkUploadBottomSheet( TextButton(onClick = { viewModel.testRule { result -> showTestResult = result } }) { - Text("测试") + AppText("测试") } Spacer(Modifier.weight(1f)) OutlinedButton(onClick = onDismiss) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } Button(onClick = { if (viewModel.saveDirectLinkRule()) { @@ -191,7 +192,7 @@ fun DirectLinkUploadBottomSheet( context.toastOnUi("请填写完整信息") } }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } @@ -200,15 +201,15 @@ fun DirectLinkUploadBottomSheet( showTestResult?.let { result -> AlertDialog( onDismissRequest = { showTestResult = null }, - title = { Text("Result") }, - text = { Text(result) }, + title = { AppText("Result") }, + text = { AppText(result) }, confirmButton = { TextButton(onClick = { showTestResult = null - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { - TextButton(onClick = { context.sendToClip(result) }) { Text(stringResource(R.string.copy_text)) } + TextButton(onClick = { context.sendToClip(result) }) { AppText(stringResource(R.string.copy_text)) } } ) } diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt index d6c6f6426..a86a882fa 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt @@ -13,7 +13,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextField import androidx.compose.runtime.Composable @@ -30,8 +29,6 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.service.WebService import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.filePicker.FilePickerSheet @@ -40,6 +37,9 @@ import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem import io.legado.app.ui.widget.components.settingItem.InputSettingItem import io.legado.app.ui.widget.components.settingItem.SliderSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.restart import io.legado.app.utils.takePersistablePermissionSafely import org.koin.androidx.compose.koinViewModel @@ -83,9 +83,7 @@ fun OtherConfigScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { - Text(stringResource(R.string.other_setting)) - }, + title = stringResource(R.string.other_setting), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) @@ -200,7 +198,10 @@ fun OtherConfigScreen( SliderSettingItem( title = stringResource(R.string.bitmap_cache_size), - description = stringResource(R.string.bitmap_cache_size_summary), + description = stringResource( + R.string.bitmap_cache_size_summary, + OtherConfig.bitmapCacheSize + ), value = OtherConfig.bitmapCacheSize.toFloat(), defaultValue = 32f, valueRange = 1f..2047f, @@ -211,7 +212,10 @@ fun OtherConfigScreen( SliderSettingItem( title = stringResource(R.string.image_retain_number), - description = stringResource(R.string.image_retain_number_summary), + description = stringResource( + R.string.image_retain_number_summary, + OtherConfig.imageRetainNum + ), value = OtherConfig.imageRetainNum.toFloat(), defaultValue = 10f, valueRange = 0f..100f, @@ -220,7 +224,10 @@ fun OtherConfigScreen( SliderSettingItem( title = stringResource(R.string.pre_download), - description = stringResource(R.string.pre_download_s), + description = stringResource( + R.string.pre_download_s, + OtherConfig.preDownloadNum + ), value = OtherConfig.preDownloadNum.toFloat(), defaultValue = 10f, valueRange = 0f..100f, @@ -458,23 +465,23 @@ fun OtherConfigScreen( if (showPasswordDialog) { AlertDialog( onDismissRequest = { showPasswordDialog = false }, - title = { Text(stringResource(R.string.set_local_password)) }, + title = { AppText(stringResource(R.string.set_local_password)) }, text = { TextField( value = tempPassword, onValueChange = { tempPassword = it }, - label = { Text("Password") } + label = { AppText("Password") } ) }, confirmButton = { TextButton(onClick = { viewModel.setLocalPassword(tempPassword) showPasswordDialog = false - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showPasswordDialog = false }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -492,16 +499,16 @@ fun ConfirmDialog( ) { AlertDialog( onDismissRequest = onDismiss, - title = { Text(title) }, - text = { Text(text) }, + title = { AppText(title) }, + text = { AppText(text) }, confirmButton = { OutlinedButton(onClick = onConfirm) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismiss) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/config/readConfig/PageKeySheet.kt b/app/src/main/java/io/legado/app/ui/config/readConfig/PageKeySheet.kt index 6e64cba0b..fe143678f 100644 --- a/app/src/main/java/io/legado/app/ui/config/readConfig/PageKeySheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/readConfig/PageKeySheet.kt @@ -11,7 +11,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -23,7 +22,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -40,16 +41,16 @@ fun PageKeySheet( .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { - Text( + AppText( text = stringResource(R.string.custom_page_key), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, fontWeight = FontWeight.Companion.Bold ) OutlinedTextField( value = prevKeys, onValueChange = { prevKeys = it }, - label = { Text(stringResource(R.string.prev_page_key)) }, + label = { AppText(stringResource(R.string.prev_page_key)) }, modifier = Modifier.Companion .fillMaxWidth() .onPreviewKeyEvent { event -> @@ -72,7 +73,7 @@ fun PageKeySheet( OutlinedTextField( value = nextKeys, onValueChange = { nextKeys = it }, - label = { Text(stringResource(R.string.next_page_key)) }, + label = { AppText(stringResource(R.string.next_page_key)) }, modifier = Modifier.Companion .fillMaxWidth() .onPreviewKeyEvent { event -> @@ -92,9 +93,9 @@ fun PageKeySheet( singleLine = true ) - Text( + AppText( text = stringResource(R.string.page_key_set_help), - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) @@ -109,7 +110,7 @@ fun PageKeySheet( }, modifier = Modifier.Companion.weight(1f) ) { - Text(stringResource(R.string.reset)) + AppText(stringResource(R.string.reset)) } Button( @@ -120,7 +121,7 @@ fun PageKeySheet( }, modifier = Modifier.Companion.weight(1f) ) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } diff --git a/app/src/main/java/io/legado/app/ui/config/readConfig/ReadConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/readConfig/ReadConfigScreen.kt index e5565d4f5..ebe4e064e 100644 --- a/app/src/main/java/io/legado/app/ui/config/readConfig/ReadConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/readConfig/ReadConfigScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -20,14 +19,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem import io.legado.app.ui.widget.components.settingItem.SliderSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.canvasrecorder.CanvasRecorderFactory import org.koin.androidx.compose.koinViewModel @@ -45,9 +44,7 @@ fun ReadConfigScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { - Text(stringResource(R.string.read_config)) - }, + title = stringResource(R.string.read_config), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) diff --git a/app/src/main/java/io/legado/app/ui/config/themeConfig/BackgroundImageManageSheet.kt b/app/src/main/java/io/legado/app/ui/config/themeConfig/BackgroundImageManageSheet.kt index f10ebfe91..2f19eb534 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeConfig/BackgroundImageManageSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeConfig/BackgroundImageManageSheet.kt @@ -17,7 +17,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -31,8 +30,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel @@ -72,9 +73,9 @@ fun BackgroundImageManageSheet( .fillMaxWidth() .padding(bottom = 24.dp) ) { - Text( + AppText( text = stringResource(R.string.background_image), - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.padding(16.dp) ) diff --git a/app/src/main/java/io/legado/app/ui/config/themeConfig/LauncherIconPickerSheet.kt b/app/src/main/java/io/legado/app/ui/config/themeConfig/LauncherIconPickerSheet.kt index 26e1ab766..e273691ec 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeConfig/LauncherIconPickerSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeConfig/LauncherIconPickerSheet.kt @@ -20,7 +20,6 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -39,7 +38,9 @@ import io.legado.app.ui.main.Launcher4 import io.legado.app.ui.main.Launcher5 import io.legado.app.ui.main.Launcher6 import io.legado.app.ui.main.LauncherW +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.getCompatDrawable import splitties.init.appCtx @@ -61,9 +62,9 @@ fun LauncherIconPickerSheet( .fillMaxWidth() .padding(bottom = 24.dp) ) { - Text( + AppText( text = stringResource(R.string.change_icon), - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.padding(16.dp) ) diff --git a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfig.kt b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfig.kt index 9337cd8d8..2902d9631 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfig.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfig.kt @@ -21,6 +21,9 @@ object ThemeConfig { var paletteStyle by prefDelegate(PreferKey.paletteStyle, "tonalSpot") + //m3 or miuix + var composeEngine by prefDelegate(PreferKey.composeEngine, "m3") + var materialVersion by prefDelegate(PreferKey.materialVersion, "material3") var appTheme by prefDelegate(PreferKey.appTheme, "0") diff --git a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt index 097287985..1cc290be3 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt @@ -44,7 +44,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.ToggleButton import androidx.compose.material3.ToggleButtonDefaults @@ -78,11 +77,10 @@ import io.legado.app.help.config.AppConfig import io.legado.app.help.config.OldThemeConfig import io.legado.app.lib.theme.ThemeStore import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.ThemeManager import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.button.TopbarNavigationButton import io.legado.app.ui.widget.components.dialog.ColorPickerSheet @@ -90,6 +88,9 @@ import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem import io.legado.app.ui.widget.components.settingItem.SliderSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import io.legado.app.utils.postEvent import io.legado.app.utils.restart import io.legado.app.utils.toastOnUi @@ -121,7 +122,7 @@ fun ThemeConfigScreen( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(stringResource(R.string.theme_setting)) }, + title = stringResource(R.string.theme_setting), scrollBehavior = scrollBehavior, navigationIcon = { TopbarNavigationButton(onClick = onBackClick) @@ -226,6 +227,13 @@ fun ThemeConfigScreen( context.toastOnUi(R.string.restart_to_apply) } ) + DropdownListSettingItem( + title = stringResource(R.string.compose_engine), + selectedValue = ThemeConfig.composeEngine, + displayEntries = stringArrayResource(R.array.composeEngine), + entryValues = stringArrayResource(R.array.composeEngine_value), + onValueChange = { ThemeConfig.composeEngine = it } + ) SliderSettingItem( title = stringResource(R.string.font_scale), description = stringResource( @@ -478,7 +486,7 @@ fun ThemeConfigScreen( if (showRestartDialog) { AlertDialog( onDismissRequest = { showRestartDialog = false }, - title = { Text(stringResource(R.string.restart_required_message)) }, + title = { AppText(stringResource(R.string.restart_required_message)) }, confirmButton = { OutlinedButton(onClick = { showRestartDialog = false @@ -486,7 +494,7 @@ fun ThemeConfigScreen( context.restart() }, 100) }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { @@ -494,7 +502,7 @@ fun ThemeConfigScreen( showRestartDialog = false context.toastOnUi(R.string.restart_later_message) }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -547,12 +555,12 @@ fun ThemeConfigScreen( saveThemeKey?.let { key -> AlertDialog( onDismissRequest = { saveThemeKey = null }, - title = { Text(stringResource(R.string.theme_name)) }, + title = { AppText(stringResource(R.string.theme_name)) }, text = { OutlinedTextField( value = themeName, onValueChange = { themeName = it }, - label = { Text("name") }, + label = { AppText("name") }, singleLine = true ) }, @@ -566,12 +574,12 @@ fun ThemeConfigScreen( saveThemeKey = null } ) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = { saveThemeKey = null }) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) @@ -623,7 +631,7 @@ fun ThemeModeSelector( Spacer(Modifier.size(ToggleButtonDefaults.IconSpacing)) - Text(text = label) + AppText(text = label) } } } @@ -745,9 +753,9 @@ fun ThemeColorButton( Spacer(modifier = Modifier.height(12.dp)) - Text( + AppText( text = label, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface ) } diff --git a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeListDialog.kt b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeListDialog.kt index da96e5864..13594b5d6 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeListDialog.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeListDialog.kt @@ -15,12 +15,10 @@ import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.FileDownload import androidx.compose.material.icons.filled.Share import androidx.compose.material3.AlertDialog -import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -38,8 +36,10 @@ import androidx.core.graphics.toColorInt import io.legado.app.R import io.legado.app.help.config.OldThemeConfig import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.GSON import io.legado.app.utils.getClipText import io.legado.app.utils.share @@ -69,9 +69,9 @@ fun ThemeListDialog( .padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp), verticalAlignment = Alignment.CenterVertically ) { - Text( + AppText( text = stringResource(R.string.theme_list), - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.weight(1f) ) IconButton( @@ -104,13 +104,11 @@ fun ThemeListDialog( .fillMaxWidth() .padding(horizontal = 16.dp), shape = RoundedCornerShape(20.dp), - colors = CardDefaults.cardColors( - containerColor = if (item.primaryColor.toColorInt() == context.primaryColor) { - MaterialTheme.colorScheme.secondaryContainer - } else { - MaterialTheme.colorScheme.surfaceContainer - } - ) + containerColor = if (item.primaryColor.toColorInt() == context.primaryColor) { + MaterialTheme.colorScheme.secondaryContainer + } else { + MaterialTheme.colorScheme.surfaceContainer + } ) { Row( modifier = Modifier @@ -129,9 +127,9 @@ fun ThemeListDialog( ) .padding(8.dp) ) - Text( + AppText( text = item.themeName, - style = MaterialTheme.typography.bodyLarge, + style = LegadoTheme.typography.bodyLarge, modifier = Modifier.weight(1f) ) IconButton( @@ -161,8 +159,8 @@ fun ThemeListDialog( deleteIndex?.let { index -> AlertDialog( onDismissRequest = { deleteIndex = null }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.sure_del)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.sure_del)) }, confirmButton = { TextButton( onClick = { @@ -171,12 +169,12 @@ fun ThemeListDialog( deleteIndex = null } ) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = { deleteIndex = null }) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleEditSheet.kt b/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleEditSheet.kt index e3c30be93..5d9f98ced 100644 --- a/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleEditSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -38,6 +37,7 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.data.entities.DictRule import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -69,7 +69,7 @@ fun DictRuleEditSheet( .verticalScroll(rememberScrollState()) ) { CenterAlignedTopAppBar( - title = { Text(stringResource(R.string.dict_rule)) }, + title = { AppText(stringResource(R.string.dict_rule)) }, navigationIcon = { IconButton(onClick = onDismissRequest) { Icon( @@ -87,7 +87,7 @@ fun DictRuleEditSheet( onDismissRequest = { showMenu = false } ) { DropdownMenuItem( - text = { Text(stringResource(R.string.copy_rule)) }, + text = { AppText(stringResource(R.string.copy_rule)) }, leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) }, onClick = { onCopy( @@ -102,7 +102,7 @@ fun DictRuleEditSheet( } ) DropdownMenuItem( - text = { Text(stringResource(R.string.paste_rule)) }, + text = { AppText(stringResource(R.string.paste_rule)) }, leadingIcon = { Icon(Icons.Default.ContentPaste, null) }, onClick = { scope.launch { @@ -132,20 +132,20 @@ fun DictRuleEditSheet( modifier = Modifier.fillMaxWidth(), value = name, onValueChange = { name = it }, - label = { Text(stringResource(R.string.name)) }, + label = { AppText(stringResource(R.string.name)) }, singleLine = true ) OutlinedTextField( modifier = Modifier.fillMaxWidth(), value = urlRule, onValueChange = { urlRule = it }, - label = { Text(stringResource(R.string.url_rule)) } + label = { AppText(stringResource(R.string.url_rule)) } ) OutlinedTextField( modifier = Modifier.fillMaxWidth(), value = showRule, onValueChange = { showRule = it }, - label = { Text(stringResource(R.string.show_rule)) }, + label = { AppText(stringResource(R.string.show_rule)) }, minLines = 3 ) } diff --git a/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleScreen.kt b/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleScreen.kt index 5ef5ec458..e157fd51d 100644 --- a/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleScreen.kt +++ b/app/src/main/java/io/legado/app/ui/dict/rule/DictRuleScreen.kt @@ -19,11 +19,9 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -46,6 +44,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.base.BaseRuleEvent import io.legado.app.data.entities.DictRule +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.DraggableSelectionHandler import io.legado.app.ui.widget.components.button.SmallIconButton @@ -59,6 +58,7 @@ import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleEditFields import io.legado.app.ui.widget.components.rules.RuleEditSheet import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.text.AppText import org.koin.androidx.compose.koinViewModel import sh.calvin.reorderable.rememberReorderableLazyListState @@ -195,8 +195,8 @@ fun DictRuleScreen( onConfirm = { viewModel.saveImportedRules() }, itemContent = { rule, _ -> Column { - Text(rule.name, style = MaterialTheme.typography.titleMedium) - Text(rule.urlRule, style = MaterialTheme.typography.bodySmall, maxLines = 1) + AppText(rule.name, style = LegadoTheme.typography.titleMedium) + AppText(rule.urlRule, style = LegadoTheme.typography.bodySmall, maxLines = 1) } } ) @@ -211,16 +211,16 @@ fun DictRuleScreen( showDeleteRuleDialog?.let { rule -> AlertDialog( onDismissRequest = { showDeleteRuleDialog = null }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.del_msg)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.del_msg)) }, confirmButton = { OutlinedButton(onClick = { viewModel.delete(rule); showDeleteRuleDialog = null - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showDeleteRuleDialog = null }) { - Text( + AppText( stringResource(R.string.cancel) ) } @@ -310,7 +310,7 @@ fun DictRuleScreen( snackbarHostState = snackbarHostState, dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_str)) }, + text = { AppText(stringResource(R.string.import_str)) }, onClick = { showImportSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.FileOpen, null) } ) diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index 6168adef4..e7778a926 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -181,7 +181,7 @@ open class MainActivity : BaseComposeActivity() { (slideIntoContainer( towards = AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween( - durationMillis = 520, + durationMillis = 480, easing = FastOutSlowInEasing ), initialOffset = { fullWidth -> fullWidth } @@ -193,7 +193,7 @@ open class MainActivity : BaseComposeActivity() { )) togetherWith (slideOutOfContainer( towards = AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween( - durationMillis = 520, + durationMillis = 480, easing = FastOutSlowInEasing ), targetOffset = { fullWidth -> fullWidth / 4 } @@ -208,7 +208,7 @@ open class MainActivity : BaseComposeActivity() { (slideIntoContainer( towards = AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween( - durationMillis = 520, + durationMillis = 480, easing = FastOutSlowInEasing ), initialOffset = { fullWidth -> -fullWidth / 4 } @@ -220,7 +220,7 @@ open class MainActivity : BaseComposeActivity() { )) togetherWith (scaleOut( targetScale = 0.8f, animationSpec = tween( - durationMillis = 520, + durationMillis = 480, easing = FastOutSlowInEasing ) ) + fadeOut( diff --git a/app/src/main/java/io/legado/app/ui/main/MainDestination.kt b/app/src/main/java/io/legado/app/ui/main/MainDestination.kt index 69569d2b0..7db8fd46c 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainDestination.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainDestination.kt @@ -12,42 +12,57 @@ import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.RssFeed import androidx.compose.ui.graphics.vector.ImageVector import io.legado.app.R +import top.yukonga.miuix.kmp.icon.MiuixIcons +import top.yukonga.miuix.kmp.icon.extended.Album +import top.yukonga.miuix.kmp.icon.extended.ContactsBook +import top.yukonga.miuix.kmp.icon.extended.Favorites +import top.yukonga.miuix.kmp.icon.extended.Settings sealed class MainDestination( val route: String, @StringRes val labelId: Int, - val icon: ImageVector, - val selectedIcon: ImageVector + val m3Icon: ImageVector, + val m3SelectedIcon: ImageVector, + val miuixIcon: ImageVector, + val miuixSelectedIcon: ImageVector ) { object Bookshelf : MainDestination( - "bookshelf", - R.string.bookshelf, - Icons.AutoMirrored.Outlined.LibraryBooks, - Icons.AutoMirrored.Filled.LibraryBooks + route = "bookshelf", + labelId = R.string.bookshelf, + m3Icon = Icons.AutoMirrored.Outlined.LibraryBooks, + m3SelectedIcon = Icons.AutoMirrored.Filled.LibraryBooks, + miuixIcon = MiuixIcons.Regular.ContactsBook, // 替换为实际的 MIUIX 线框图标 + miuixSelectedIcon = MiuixIcons.Heavy.ContactsBook // 替换为实际的 MIUIX 填充图标 ) object Explore : MainDestination( - "explore", - R.string.discovery, - Icons.Outlined.Explore, - Icons.Default.Explore + route = "explore", + labelId = R.string.discovery, + m3Icon = Icons.Outlined.Explore, + m3SelectedIcon = Icons.Default.Explore, + miuixIcon = MiuixIcons.Regular.Album, + miuixSelectedIcon = MiuixIcons.Heavy.Album ) object Rss : MainDestination( - "rss", - R.string.rss, - Icons.Outlined.RssFeed, - Icons.Default.RssFeed + route = "rss", + labelId = R.string.rss, + m3Icon = Icons.Outlined.RssFeed, + m3SelectedIcon = Icons.Default.RssFeed, + miuixIcon = MiuixIcons.Regular.Favorites, + miuixSelectedIcon = MiuixIcons.Heavy.Favorites ) object My : MainDestination( - "my", - R.string.my, - Icons.Outlined.Person, - Icons.Default.Person + route = "my", + labelId = R.string.my, + m3Icon = Icons.Outlined.Person, + m3SelectedIcon = Icons.Default.Person, + miuixIcon = MiuixIcons.Regular.Settings, + miuixSelectedIcon = MiuixIcons.Heavy.Settings ) companion object { val mainDestinations = listOf(Bookshelf, Explore, Rss, My) } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/main/MainScreen.kt b/app/src/main/java/io/legado/app/ui/main/MainScreen.kt index 4f9398bcb..5ed27fa30 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainScreen.kt @@ -20,17 +20,12 @@ import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Badge import androidx.compose.material3.BadgedBox -import androidx.compose.material3.BottomAppBarDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults -import androidx.compose.material3.Text import androidx.compose.material3.WideNavigationRail import androidx.compose.material3.WideNavigationRailItem import androidx.compose.material3.WideNavigationRailValue @@ -56,17 +51,19 @@ import io.legado.app.R import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.config.mainConfig.MainConfig -import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.main.bookshelf.BookshelfScreen import io.legado.app.ui.main.bookshelf.BookshelfViewModel import io.legado.app.ui.main.explore.ExploreScreen import io.legado.app.ui.main.my.MyScreen import io.legado.app.ui.main.rss.RssScreen import io.legado.app.ui.theme.regularHazeEffect +import io.legado.app.ui.widget.components.AppNavigationBar +import io.legado.app.ui.widget.components.AppNavigationBarItem import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.GlassDefaults import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.startActivity import io.legado.app.utils.startActivityForBook import kotlinx.coroutines.launch @@ -151,7 +148,7 @@ fun MainScreen( onClick = { context.startActivity() }, expanded = expanded, icon = { Icon(Icons.Default.Search, contentDescription = null) }, - text = { Text(stringResource(R.string.search)) } + text = { AppText(stringResource(R.string.search)) } ) } } @@ -198,7 +195,7 @@ fun MainScreen( ) { dismiss -> bookshelfUiState.groups.forEachIndexed { groupIndex, group -> RoundDropdownMenuItem( - text = { Text(group.groupName) }, + text = { AppText(group.groupName) }, onClick = { coroutineScope.launch { if (pagerState.currentPage != index) { @@ -224,7 +221,7 @@ fun MainScreen( } }, label = if (labelVisibilityMode != "unlabeled") { - { Text(stringResource(destination.labelId)) } + { AppText(stringResource(destination.labelId)) } } else null ) } @@ -237,103 +234,34 @@ fun MainScreen( if (!useRail && MainConfig.showBottomView) { val labelVisibilityMode = MainConfig.labelVisibilityMode val isUnlabeled = labelVisibilityMode == "unlabeled" - NavigationBar( + + AppNavigationBar( modifier = Modifier .regularHazeEffect(state = hazeState) - .height(if (isUnlabeled) 64.dp else 80.dp), - containerColor = GlassDefaults.glassColor( - noBlurColor = BottomAppBarDefaults.containerColor, - blurAlpha = GlassDefaults.DefaultBlurAlpha - ).let { baseColor -> - val opacity = (ThemeConfig.bottomBarOpacity.coerceIn(0, 100)) / 100f - baseColor.copy(alpha = (baseColor.alpha * opacity).coerceIn(0f, 1f)) - } + .height(if (isUnlabeled) 64.dp else 80.dp) ) { val alwaysShowLabel = when (labelVisibilityMode) { "labeled" -> true - "selected" -> false - "unlabeled" -> false else -> false } destinations.forEachIndexed { index, destination -> val selected = pagerState.targetPage == index - var showGroupMenu by remember { mutableStateOf(false) } - val haptic = LocalHapticFeedback.current - - NavigationBarItem( + AppNavigationBarItem( selected = selected, onClick = { - coroutineScope.launch { - pagerState.animateScrollToPage(index) - } + coroutineScope.launch { pagerState.animateScrollToPage(index) } }, - icon = { - Box { - NavigationIcon( - destination = destination, - selected = selected, - upBooksCount = uiState.upBooksCount, - modifier = if (destination == MainDestination.Bookshelf) { - Modifier.combinedClickable( - onClick = { - coroutineScope.launch { - pagerState.animateScrollToPage(index) - } - }, - onLongClick = { - haptic.performHapticFeedback( - HapticFeedbackType.LongPress - ) - showGroupMenu = true - } - ) - } else Modifier - ) - - if (destination == MainDestination.Bookshelf && showGroupMenu) { - RoundDropdownMenu( - expanded = showGroupMenu, - onDismissRequest = { showGroupMenu = false } - ) { dismiss -> - bookshelfUiState.groups.forEachIndexed { groupIndex, group -> - RoundDropdownMenuItem( - text = { Text(group.groupName) }, - onClick = { - coroutineScope.launch { - if (pagerState.currentPage != index) { - pagerState.scrollToPage(index) - } - bookshelfViewModel.changeGroup( - group.groupId - ) - dismiss() - } - }, - trailingIcon = { - if (bookshelfUiState.selectedGroupIndex == groupIndex) { - Icon( - Icons.Default.Check, - null, - modifier = Modifier.size(18.dp) - ) - } - } - ) - } - } - } - } + labelString = stringResource(destination.labelId), + miuixIcon = if (selected) destination.miuixSelectedIcon else destination.miuixIcon, + m3Icon = { + if (selected) destination.m3SelectedIcon else destination.m3Icon }, - colors = NavigationBarItemDefaults.colors( - indicatorColor = GlassDefaults.glassColor( - noBlurColor = MaterialTheme.colorScheme.secondaryContainer, - blurAlpha = GlassDefaults.ThickBlurAlpha - ), + m3IndicatorColor = GlassDefaults.glassColor( + noBlurColor = MaterialTheme.colorScheme.secondaryContainer, + blurAlpha = GlassDefaults.ThickBlurAlpha ), - label = if (labelVisibilityMode != "unlabeled") { - { Text(stringResource(destination.labelId)) } - } else null, - alwaysShowLabel = alwaysShowLabel + m3ShowLabel = !isUnlabeled, + m3AlwaysShowLabel = alwaysShowLabel ) } } @@ -386,10 +314,10 @@ private fun NavigationIcon( upBooksCount: Int, modifier: Modifier = Modifier ) { - val icon = if (selected) destination.selectedIcon else destination.icon + val icon = if (selected) destination.m3SelectedIcon else destination.m3Icon Box(modifier = modifier) { if (destination == MainDestination.Bookshelf && upBooksCount > 0) { - BadgedBox(badge = { Badge { Text(upBooksCount.toString()) } }) { + BadgedBox(badge = { Badge { AppText(upBooksCount.toString()) } }) { Icon(icon, contentDescription = null) } } else { diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt index 3bdeb0c58..a443f1955 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt @@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -34,9 +33,11 @@ import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.data.entities.BookGroup import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.cover.BookCover import io.legado.app.ui.widget.components.cover.BookshelfCover import io.legado.app.ui.widget.components.cover.Cover +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.toTimeAgo /** @@ -88,9 +89,9 @@ fun BookshelfItem( ) { cover(Modifier.fillMaxSize()) if (gridStyle == 1) { - Text( + AppText( text = title, - style = (if (titleSmallFont) MaterialTheme.typography.labelSmall else MaterialTheme.typography.labelMedium).copy( + style = (if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium).copy( color = Color.White, shadow = Shadow( color = Color.Black.copy(alpha = 0.5f), @@ -117,9 +118,9 @@ fun BookshelfItem( } if (gridStyle == 0) { - Text( + AppText( text = title, - style = if (titleSmallFont) MaterialTheme.typography.labelSmall else MaterialTheme.typography.labelMedium, + style = if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium, maxLines = titleMaxLines, overflow = TextOverflow.Ellipsis, textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start, @@ -152,16 +153,16 @@ fun BookshelfItem( modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center ) { - Text( + AppText( text = title, - style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold), + style = LegadoTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold), maxLines = if (!isCompact) 2 else 1, overflow = TextOverflow.Ellipsis ) subTitle?.let { - Text( + AppText( text = it, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.padding(top = 2.dp) @@ -169,9 +170,9 @@ fun BookshelfItem( } if (!isCompact) { desc?.let { - Text( + AppText( text = it, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.padding(top = 2.dp) @@ -372,7 +373,7 @@ fun BookItem( isUpdating = isUpdating, modifier = modifier, badgeText = if (BookshelfConfig.showUnread && unreadCount > 0) unreadCount.toString() else null, - showBadgeDot = !BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && unreadCount > 0 + showBadgeDot = BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && book.isNew ) }, title = book.name, @@ -384,16 +385,16 @@ fun BookItem( desc = stringResource(R.string.read_dur_progress, book.durChapterTitle ?: ""), extra = { if (BookshelfConfig.showLastUpdateTime && !book.isLocal) { - Text( + AppText( text = book.latestChapterTime.toTimeAgo(), - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = if (layoutMode != 0 || !isCompact) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary, modifier = Modifier.padding(end = 4.dp) ) } - Text( + AppText( text = book.latestChapterTitle ?: "", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt index a588eb524..e7717278d 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt @@ -16,6 +16,7 @@ data class BookShelfItem( val durChapterPos: Int, val latestChapterTitle: String?, val latestChapterTime: Long, + val lastCheckCount: Int, val totalChapterNum: Int, val durChapterIndex: Int, val type: Int, @@ -33,5 +34,8 @@ data class BookShelfItem( val isNotShelf: Boolean get() = (type and BookType.notShelf) > 0 + val isNew: Boolean get() = lastCheckCount > 0 + + fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0) } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfConfigSheet.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfConfigSheet.kt index b9195137f..10c5bc5cd 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfConfigSheet.kt @@ -23,7 +23,6 @@ import androidx.compose.material.icons.filled.TextFormat import androidx.compose.material.icons.filled.ViewCompact import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration @@ -32,10 +31,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem import io.legado.app.ui.widget.components.settingItem.CompactSliderSettingItem import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -55,9 +56,9 @@ fun BookshelfConfigSheet( .padding(bottom = 32.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( + AppText( text = stringResource(R.string.bookshelf_layout), - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(vertical = 16.dp) ) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt index 98e872661..76dcafcce 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt @@ -45,7 +45,7 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Surface import androidx.compose.material3.Tab -import androidx.compose.material3.Text +import io.legado.app.ui.widget.components.text.AppText import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults import androidx.compose.material3.pulltorefresh.pullToRefresh import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState @@ -78,6 +78,7 @@ import io.legado.app.ui.book.import.remote.RemoteBookActivity import io.legado.app.ui.book.manage.BookshelfManageActivity import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.button.SmallOutlinedIconToggleButton import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.importComponents.SourceInputDialog @@ -85,6 +86,7 @@ import io.legado.app.ui.widget.components.lazylist.FastScrollLazyVerticalGrid import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.tabRow.AdaptiveTabRow import io.legado.app.utils.readText import io.legado.app.utils.startActivity import io.legado.app.utils.toastOnUi @@ -235,37 +237,37 @@ fun BookshelfScreen( topBarActions = { }, dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.add_remote_book)) }, + text = { AppText(stringResource(R.string.add_remote_book)) }, onClick = { context.startActivity(); dismiss() }, leadingIcon = { Icon(Icons.Default.Wifi, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.book_local)) }, + text = { AppText(stringResource(R.string.book_local)) }, onClick = { context.startActivity(); dismiss() }, leadingIcon = { Icon(Icons.Default.Save, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.update_toc)) }, + text = { AppText(stringResource(R.string.update_toc)) }, onClick = { viewModel.upToc(uiState.items); dismiss() }, leadingIcon = { Icon(Icons.Default.Refresh, null) } ) RoundDropdownMenuItem( - text = { Text("布局设置") }, + text = { AppText("布局设置") }, onClick = { showConfigSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.GridView, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.group_manage)) }, + text = { AppText(stringResource(R.string.group_manage)) }, onClick = { showGroupManageSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.Edit, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.add_url)) }, + text = { AppText(stringResource(R.string.add_url)) }, onClick = { showAddUrlDialog = true; dismiss() }, leadingIcon = { Icon(Icons.Default.Link, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.bookshelf_management)) }, + text = { AppText(stringResource(R.string.bookshelf_management)) }, onClick = { val groupId = uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L @@ -277,7 +279,7 @@ fun BookshelfScreen( leadingIcon = { Icon(Icons.Default.Settings, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.cache_export)) }, + text = { AppText(stringResource(R.string.cache_export)) }, onClick = { val groupId = uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L @@ -289,7 +291,7 @@ fun BookshelfScreen( leadingIcon = { Icon(Icons.Default.Download, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.export_bookshelf)) }, + text = { AppText(stringResource(R.string.export_bookshelf)) }, onClick = { showExportSheet = true dismiss() @@ -297,12 +299,12 @@ fun BookshelfScreen( leadingIcon = { Icon(Icons.Default.ImportExport, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_bookshelf)) }, + text = { AppText(stringResource(R.string.import_bookshelf)) }, onClick = { showImportSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.FileOpen, null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.log)) }, + text = { AppText(stringResource(R.string.log)) }, onClick = { showLogSheet = true dismiss() @@ -320,33 +322,19 @@ fun BookshelfScreen( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { - PrimaryScrollableTabRow( - selectedTabIndex = selectedTabIndex, - edgePadding = 0.dp, - divider = { }, - containerColor = Color.Transparent, - minTabWidth = 0.dp, - modifier = Modifier.weight(1f) - ) { - uiState.groups.forEachIndexed { index, group -> - Tab( - selected = selectedTabIndex == index, - onClick = { - scope.launch { pagerState.animateScrollToPage(index) } - }, - text = { - Text( - text = group.groupName, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(horizontal = 8.dp), - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - ) - } + val tabTitles = remember(uiState.groups) { + uiState.groups.map { it.groupName } } + AdaptiveTabRow( + tabTitles = tabTitles, + selectedTabIndex = selectedTabIndex, + onTabSelected = { index -> + scope.launch { pagerState.animateScrollToPage(index) } + }, + modifier = Modifier.weight(1f) + ) + if (BookshelfConfig.shouldShowExpandButton) { Box(modifier = Modifier.padding(end = 16.dp)) { SmallOutlinedIconToggleButton( @@ -361,7 +349,7 @@ fun BookshelfScreen( ) { dismiss -> uiState.groups.forEachIndexed { index, group -> RoundDropdownMenuItem( - text = { Text(group.groupName) }, + text = { AppText(group.groupName) }, onClick = { scope.launch { pagerState.animateScrollToPage(index) } dismiss() @@ -565,10 +553,10 @@ fun BookshelfScreen( ) { CircularProgressIndicator() uiState.loadingText?.let { - Text( + AppText( text = it, modifier = Modifier.padding(top = 16.dp), - style = MaterialTheme.typography.bodyMedium + style = LegadoTheme.typography.bodyMedium ) } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/GroupManageSheet.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/GroupManageSheet.kt index 765a58bbf..7149b5f13 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/GroupManageSheet.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/GroupManageSheet.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -36,8 +35,10 @@ import io.legado.app.R import io.legado.app.data.entities.BookGroup import io.legado.app.ui.book.group.GroupEditContent import io.legado.app.ui.book.group.GroupViewModel +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.card.ReorderableSelectionItem import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.move import org.koin.androidx.compose.koinViewModel import sh.calvin.reorderable.rememberReorderableLazyListState @@ -104,9 +105,9 @@ fun GroupManageSheet( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( + AppText( text = stringResource(R.string.group_manage), - style = MaterialTheme.typography.titleLarge + style = LegadoTheme.typography.titleLarge ) IconButton(onClick = { editingGroup = null diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt index 562e0ebbb..f624b8934 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt @@ -43,7 +43,6 @@ import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.LocalMinimumInteractiveComponentSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -73,6 +72,9 @@ import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.book.search.SearchScope import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.login.SourceLoginActivity +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.divider.PillHeaderDivider @@ -81,9 +83,11 @@ import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.menuItem.MenuItemIcon import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.startActivity import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel +import top.yukonga.miuix.kmp.theme.MiuixTheme import kotlin.math.roundToInt @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @@ -148,13 +152,13 @@ fun ExploreScreen( dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Group) }, - text = { Text(stringResource(R.string.all)) }, + text = { AppText(stringResource(R.string.all)) }, onClick = { viewModel.setGroup(""); dismiss() } ) uiState.groups.forEach { group -> RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) }, - text = { Text(group) }, + text = { AppText(group) }, onClick = { viewModel.setGroup(group); dismiss() } ) } @@ -274,19 +278,19 @@ fun ExploreScreen( sourceToDelete?.let { source -> AlertDialog( onDismissRequest = { sourceToDelete = null }, - title = { Text(stringResource(R.string.draw)) }, - text = { Text(stringResource(R.string.sure_del) + "\n" + source.bookSourceName) }, + title = { AppText(stringResource(R.string.draw)) }, + text = { AppText(stringResource(R.string.sure_del) + "\n" + source.bookSourceName) }, confirmButton = { TextButton(onClick = { viewModel.deleteSource(source) sourceToDelete = null }) { - Text(stringResource(R.string.yes)) + AppText(stringResource(R.string.yes)) } }, dismissButton = { TextButton(onClick = { sourceToDelete = null }) { - Text(stringResource(R.string.no)) + AppText(stringResource(R.string.no)) } } ) @@ -344,11 +348,22 @@ fun ExploreSourceHeader( ) { var showMenu by remember { mutableStateOf(false) } val rotation by animateFloatAsState(if (isExpanded) 90f else 0f, label = "rotation") + + val composeEngine = ThemeResolver.isMiuixEngine(composeEngine) val containerColor by animateColorAsState( targetValue = if (isExpanded) - MaterialTheme.colorScheme.secondaryContainer + if (composeEngine) MiuixTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.secondaryContainer else - MaterialTheme.colorScheme.surfaceContainerLow, + if (composeEngine) MiuixTheme.colorScheme.surfaceContainer else MaterialTheme.colorScheme.surfaceContainerLow, + animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing), + label = "CardColor" + ) + + val contentColor by animateColorAsState( + targetValue = if (isExpanded) + if (composeEngine) MiuixTheme.colorScheme.primary else MaterialTheme.colorScheme.primary + else + if (composeEngine) MiuixTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onSurface, animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing), label = "CardColor" ) @@ -358,7 +373,7 @@ fun ExploreSourceHeader( .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 4.dp), shape = MaterialTheme.shapes.medium, - colors = CardDefaults.cardColors(containerColor = containerColor), + containerColor = containerColor ) { ListItem( modifier = Modifier @@ -371,14 +386,10 @@ fun ExploreSourceHeader( containerColor = Color.Transparent ), headlineContent = { - Text( + AppText( text = item.bookSourceName, - style = MaterialTheme.typography.titleMedium, - color = if (isExpanded) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - } + style = LegadoTheme.typography.titleMedium, + color = contentColor ) }, trailingContent = { @@ -401,29 +412,29 @@ fun ExploreSourceHeader( PillHeaderDivider(title = item.bookSourceName) RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) }, - text = { Text(stringResource(R.string.to_top)) }, + text = { AppText(stringResource(R.string.to_top)) }, onClick = { onTop(); showMenu = false } ) RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Edit) }, - text = { Text(stringResource(R.string.edit)) }, + text = { AppText(stringResource(R.string.edit)) }, onClick = { onEdit(); showMenu = false } ) RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Search) }, - text = { Text(stringResource(R.string.search)) }, + text = { AppText(stringResource(R.string.search)) }, onClick = { onSearch(); showMenu = false } ) if (item.hasLoginUrl) { RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) }, - text = { Text(stringResource(R.string.login)) }, + text = { AppText(stringResource(R.string.login)) }, onClick = { onLogin(); showMenu = false } ) } RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Refresh) }, - text = { Text(stringResource(R.string.refresh)) }, + text = { AppText(stringResource(R.string.refresh)) }, onClick = { onRefresh(); showMenu = false } ) RoundDropdownMenuItem( @@ -434,7 +445,7 @@ fun ExploreSourceHeader( ) }, text = { - Text( + AppText( stringResource(R.string.delete), color = MaterialTheme.colorScheme.error ) @@ -455,7 +466,7 @@ fun ExploreStickyCard( TextCard( text = item.bookSourceName, backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh, - textStyle = MaterialTheme.typography.labelLarge, + textStyle = LegadoTheme.typography.labelLarge, horizontalPadding = 8.dp, verticalPadding = 6.dp, onClick = onClick @@ -479,10 +490,8 @@ fun ExploreKindItem( GlassCard( onClick = onClick, shape = shape, - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f), - contentColor = MaterialTheme.colorScheme.onSecondaryContainer - ), + containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f), + contentColor = MaterialTheme.colorScheme.onSecondaryContainer, modifier = modifier ) { KindText(kind) @@ -506,12 +515,12 @@ fun ExploreKindItem( private fun KindText( kind: ExploreKind ) { - Text( + AppText( text = kind.title, modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp), - style = MaterialTheme.typography.labelMediumEmphasized, + style = LegadoTheme.typography.labelMediumEmphasized, textAlign = TextAlign.Center, overflow = TextOverflow.Ellipsis, maxLines = 1 diff --git a/app/src/main/java/io/legado/app/ui/main/my/MyScreen.kt b/app/src/main/java/io/legado/app/ui/main/my/MyScreen.kt index d23e1a50b..f752583fa 100644 --- a/app/src/main/java/io/legado/app/ui/main/my/MyScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/my/MyScreen.kt @@ -1,13 +1,20 @@ package io.legado.app.ui.main.my +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -16,20 +23,19 @@ import androidx.compose.material.icons.automirrored.filled.HelpOutline import androidx.compose.material.icons.automirrored.filled.LibraryBooks import androidx.compose.material.icons.automirrored.filled.Rule import androidx.compose.material.icons.filled.Bookmark +import androidx.compose.material.icons.filled.ContentCopy import androidx.compose.material.icons.filled.FindReplace import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.OpenInBrowser import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Source import androidx.compose.material.icons.filled.Web -import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.Switch -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -46,11 +52,14 @@ import io.legado.app.ui.book.toc.rule.TxtTocRuleActivity import io.legado.app.ui.dict.rule.DictRuleActivity import io.legado.app.ui.file.FileManageActivity import io.legado.app.ui.replace.ReplaceRuleActivity +import io.legado.app.ui.theme.adaptiveHorizontalPadding import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SplicedColumnGroup -import io.legado.app.ui.widget.components.settingItem.SettingItem +import io.legado.app.ui.widget.components.button.SmallTextButton +import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem +import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @@ -70,11 +79,7 @@ fun MyScreen( .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top), topBar = { GlassMediumFlexibleTopAppBar( - title = { - Text( - text = stringResource(R.string.my) - ) - }, + title = stringResource(R.string.my), actions = { IconButton( onClick = { onNavigate(PrefClickEvent.ShowMd("appHelp", "xxx")) } @@ -99,52 +104,21 @@ fun MyScreen( ) SplicedColumnGroup( - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.adaptiveHorizontalPadding(), title = "" ) { - SettingItem( - title = stringResource(R.string.web_service), - description = if (uiState.isWebServiceRun) - uiState.webServiceAddress - else - stringResource(R.string.web_service_desc), - imageVector = Icons.Default.Web, - trailingContent = { - Switch( - checked = uiState.isWebServiceRun, - onCheckedChange = { - viewModel.onEvent(PrefClickEvent.ToggleWebService) - } - ) - }, - dropdownMenu = if (uiState.isWebServiceRun) { - { onDismiss -> - DropdownMenuItem( - text = { Text("复制地址") }, - onClick = { - onNavigate(PrefClickEvent.CopyUrl(uiState.webServiceAddress)) - onDismiss() - } - ) - DropdownMenuItem( - text = { Text("浏览器打开") }, - onClick = { - onNavigate(PrefClickEvent.OpenUrl(uiState.webServiceAddress)) - onDismiss() - } - ) - } - } else null, - onClick = { } + WebServiceSettingBlock( + uiState = uiState, + viewModel = viewModel, + onNavigate = onNavigate ) } - SplicedColumnGroup( - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.adaptiveHorizontalPadding(), title = "规则" ) { - SettingItem( + ClickableSettingItem( title = stringResource(R.string.book_source_manage), description = stringResource(R.string.book_source_manage_desc), imageVector = Icons.Default.Source, @@ -154,7 +128,7 @@ fun MyScreen( ) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.replace_purify), imageVector = Icons.Default.FindReplace, onClick = { @@ -163,7 +137,7 @@ fun MyScreen( ) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.txt_toc_rule), imageVector = Icons.AutoMirrored.Filled.Rule, onClick = { @@ -172,7 +146,7 @@ fun MyScreen( ) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.dict_rule), imageVector = Icons.AutoMirrored.Filled.LibraryBooks, onClick = { @@ -184,44 +158,44 @@ fun MyScreen( } SplicedColumnGroup( - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.adaptiveHorizontalPadding(), title = stringResource(R.string.other)) { - SettingItem( + ClickableSettingItem( title = stringResource(R.string.setting), imageVector = Icons.Default.Settings, onClick = { onOpenSettings() } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.bookmark), imageVector = Icons.Default.Bookmark, onClick = { onNavigate(PrefClickEvent.StartActivity(AllBookmarkActivity::class.java)) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.read_record), imageVector = Icons.Default.History, onClick = { onNavigate(PrefClickEvent.StartActivity(ReadRecordActivity::class.java)) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.file_manage), imageVector = Icons.Default.Folder, onClick = { onNavigate(PrefClickEvent.StartActivity(FileManageActivity::class.java)) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.about), imageVector = Icons.Default.Info, onClick = { onNavigate(PrefClickEvent.StartActivity(AboutActivity::class.java)) } ) - SettingItem( + ClickableSettingItem( title = stringResource(R.string.exit), imageVector = Icons.AutoMirrored.Filled.ExitToApp, onClick = { @@ -234,3 +208,58 @@ fun MyScreen( } } } + + +@Composable +fun WebServiceSettingBlock( + uiState: MyUiState, + viewModel: MyViewModel, + onNavigate: (PrefClickEvent) -> Unit +) { + Column(modifier = Modifier.fillMaxWidth()) { + SwitchSettingItem( + title = stringResource(R.string.web_service), + description = if (uiState.isWebServiceRun) { + uiState.webServiceAddress + } else { + stringResource(R.string.web_service_desc) + }, + imageVector = Icons.Default.Web, + checked = uiState.isWebServiceRun, + onCheckedChange = { + viewModel.onEvent(PrefClickEvent.ToggleWebService) + } + ) + + AnimatedVisibility( + visible = uiState.isWebServiceRun, + enter = expandVertically(), + exit = shrinkVertically() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 12.dp), + horizontalArrangement = Arrangement.End + ) { + SmallTextButton( + text = "复制地址", + icon = Icons.Default.ContentCopy, + onClick = { + onNavigate(PrefClickEvent.CopyUrl(uiState.webServiceAddress)) + } + ) + + Spacer(modifier = Modifier.width(12.dp)) + + SmallTextButton( + text = "浏览器打开", + icon = Icons.Default.OpenInBrowser, + onClick = { + onNavigate(PrefClickEvent.OpenUrl(uiState.webServiceAddress)) + } + ) + } + } + } +} diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt index f86a76602..3a25954cf 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.material.icons.filled.VerticalAlignTop import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -55,6 +54,7 @@ import io.legado.app.ui.rss.read.ReadRssActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.manage.RssSourceActivity import io.legado.app.ui.rss.subscription.RuleSubActivity +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.SourceIcon import io.legado.app.ui.widget.components.button.TopBarActionButton import io.legado.app.ui.widget.components.divider.PillDivider @@ -63,6 +63,7 @@ import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.menuItem.MenuItemIcon import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.openUrl import io.legado.app.utils.startActivity import org.koin.androidx.compose.koinViewModel @@ -135,12 +136,12 @@ fun RssScreen( dismiss() }, leadingIcon = { MenuItemIcon(Icons.Default.Settings) }, - text = { Text("订阅源管理") } + text = { AppText("订阅源管理") } ) PillDivider() RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Group) }, - text = { Text(stringResource(R.string.all)) }, + text = { AppText(stringResource(R.string.all)) }, onClick = { viewModel.setGroup("") dismiss() @@ -149,7 +150,7 @@ fun RssScreen( uiState.groups.forEach { group -> RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) }, - text = { Text(group) }, + text = { AppText(group) }, onClick = { viewModel.setGroup(group) dismiss() @@ -188,8 +189,8 @@ fun RssScreen( sourceToDelete?.let { source -> AlertDialog( onDismissRequest = { sourceToDelete = null }, - title = { Text(stringResource(R.string.draw)) }, - text = { Text(stringResource(R.string.sure_del) + "\n" + source.sourceName) }, + title = { AppText(stringResource(R.string.draw)) }, + text = { AppText(stringResource(R.string.sure_del) + "\n" + source.sourceName) }, confirmButton = { TextButton( onClick = { @@ -197,12 +198,12 @@ fun RssScreen( sourceToDelete = null } ) { - Text(stringResource(R.string.yes)) + AppText(stringResource(R.string.yes)) } }, dismissButton = { TextButton(onClick = { sourceToDelete = null }) { - Text(stringResource(R.string.no)) + AppText(stringResource(R.string.no)) } } ) @@ -246,7 +247,7 @@ fun RssSourceGridItem( PillHeaderDivider(title = source.sourceName) RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) }, - text = { Text(stringResource(R.string.to_top)) }, + text = { AppText(stringResource(R.string.to_top)) }, onClick = { onTop() showMenu = false @@ -254,7 +255,7 @@ fun RssSourceGridItem( ) RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Edit) }, - text = { Text(stringResource(R.string.edit)) }, + text = { AppText(stringResource(R.string.edit)) }, onClick = { onEdit() showMenu = false @@ -263,7 +264,7 @@ fun RssSourceGridItem( if (!source.loginUrl.isNullOrBlank()) { RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) }, - text = { Text(stringResource(R.string.login)) }, + text = { AppText(stringResource(R.string.login)) }, onClick = { onLogin() showMenu = false @@ -272,7 +273,7 @@ fun RssSourceGridItem( } RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Close) }, - text = { Text(stringResource(R.string.disable_source)) }, + text = { AppText(stringResource(R.string.disable_source)) }, onClick = { onDisable() showMenu = false @@ -286,7 +287,7 @@ fun RssSourceGridItem( ) }, text = { - Text( + AppText( stringResource(R.string.delete), color = MaterialTheme.colorScheme.error ) @@ -299,9 +300,9 @@ fun RssSourceGridItem( } } Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = source.sourceName, - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, maxLines = 2, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, diff --git a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleScreen.kt b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleScreen.kt index 1990471ea..3cb2cf8f2 100644 --- a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleScreen.kt +++ b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -26,14 +25,10 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.LoadingIndicator -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.PlainTooltip -import androidx.compose.material3.PrimaryScrollableTabRow import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult -import androidx.compose.material3.Tab -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox @@ -50,20 +45,19 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.ClipEntry import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.base.BaseRuleEvent import io.legado.app.data.entities.ReplaceRule +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.DraggableSelectionHandler import io.legado.app.ui.widget.components.GroupManageBottomSheet @@ -76,6 +70,8 @@ import io.legado.app.ui.widget.components.importComponents.SourceInputDialog import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.tabRow.AdaptiveTabRow +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel import sh.calvin.reorderable.rememberReorderableLazyListState @@ -207,9 +203,9 @@ fun ReplaceRuleScreen( topBarActions = {}, itemContent = { rule, _ -> Column { - Text(rule.name, style = MaterialTheme.typography.titleMedium) + AppText(rule.name, style = LegadoTheme.typography.titleMedium) if (!rule.group.isNullOrBlank()) { - Text(rule.group!!, style = MaterialTheme.typography.bodySmall) + AppText(rule.group!!, style = LegadoTheme.typography.bodySmall) } } } @@ -279,16 +275,16 @@ fun ReplaceRuleScreen( showDeleteRuleDialog?.let { rule -> AlertDialog( onDismissRequest = { showDeleteRuleDialog = null }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.del_msg)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.del_msg)) }, confirmButton = { OutlinedButton(onClick = { viewModel.delete(rule); showDeleteRuleDialog = null - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showDeleteRuleDialog = null }) { - Text( + AppText( stringResource(R.string.cancel) ) } @@ -347,39 +343,21 @@ fun ReplaceRuleScreen( }, bottomContent = { if (tabItems.size > 1) { - PrimaryScrollableTabRow( - selectedTabIndex = selectedTabIndex.coerceAtMost(tabItems.size - 1) - .coerceAtLeast(0), - edgePadding = 0.dp, - divider = {}, - containerColor = Color.Transparent, - ) { - tabItems.forEachIndexed { index, title -> - Tab( - selected = selectedTabIndex == index, - onClick = { - selectedTabIndex = index - viewModel.setGroup(title) - }, - text = { - Text( - text = title, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(horizontal = 16.dp), - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - ) + AdaptiveTabRow( + tabTitles = tabItems, + selectedTabIndex = selectedTabIndex, + onTabSelected = { index -> + selectedTabIndex = index + viewModel.setGroup(tabItems[index]) } - } + ) } }, floatingActionButton = { TooltipBox( positionProvider = TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), - tooltip = { PlainTooltip { Text("Localized description") } }, + tooltip = { PlainTooltip { AppText("Localized description") } }, state = rememberTooltipState(), ) { with(sharedTransitionScope) { @@ -406,29 +384,29 @@ fun ReplaceRuleScreen( snackbarHostState = snackbarHostState, dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_str)) }, + text = { AppText(stringResource(R.string.import_str)) }, onClick = { showImportSheet = true; dismiss() }, leadingIcon = { Icon(Icons.Default.FileOpen, null) } ) RoundDropdownMenuItem( - text = { Text("分组管理") }, + text = { AppText("分组管理") }, onClick = { showGroupManageSheet = true; dismiss() } ) RoundDropdownMenuItem( - text = { Text("帮助") }, + text = { AppText("帮助") }, onClick = { /*TODO*/ dismiss() } ) PillDivider() RoundDropdownMenuItem( - text = { Text("旧的在前") }, + text = { AppText("旧的在前") }, onClick = { viewModel.setSortMode("asc"); dismiss() } ) RoundDropdownMenuItem( - text = { Text("新的在前") }, + text = { AppText("新的在前") }, onClick = { viewModel.setSortMode("desc"); dismiss() } ) RoundDropdownMenuItem( - text = { Text("名称升序") }, + text = { AppText("名称升序") }, onClick = { viewModel.setSortMode("name_asc") dismiss() @@ -438,7 +416,7 @@ fun ReplaceRuleScreen( } ) RoundDropdownMenuItem( - text = { Text("名称降序") }, + text = { AppText("名称降序") }, onClick = { viewModel.setSortMode("name_desc") dismiss() @@ -496,15 +474,15 @@ fun ReplaceRuleScreen( ), dropdownContent = { dismiss -> DropdownMenuItem( - text = { Text("移至顶部") }, + text = { AppText("移至顶部") }, onClick = { viewModel.toTop(ui.rule); dismiss() } ) DropdownMenuItem( - text = { Text("移至底部") }, + text = { AppText("移至底部") }, onClick = { viewModel.toBottom(ui.rule); dismiss() } ) DropdownMenuItem( - text = { Text("删除") }, + text = { AppText("删除") }, onClick = { showDeleteRuleDialog = ui.rule; dismiss() } ) } diff --git a/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditScreen.kt b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditScreen.kt index cd8164437..5e473d408 100644 --- a/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditScreen.kt +++ b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditScreen.kt @@ -52,7 +52,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.PlainTooltip -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox @@ -78,10 +77,11 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.button.AlertButton import io.legado.app.ui.widget.components.button.TopbarNavigationButton +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import org.koin.androidx.compose.koinViewModel @Composable @@ -119,7 +119,7 @@ fun ReplaceEditScreen( .imePadding(), topBar = { GlassMediumFlexibleTopAppBar( - title = { Text(if (state.id > 0) "编辑替换规则" else "新增替换规则") }, + title = if (state.id > 0) "编辑替换规则" else "新增替换规则", navigationIcon = { TopbarNavigationButton(onClick = onBack) }, @@ -143,14 +143,14 @@ fun ReplaceEditScreen( onDismissRequest = { showMenu = false } ) { DropdownMenuItem( - text = { Text("复制规则") }, + text = { AppText("复制规则") }, onClick = { showMenu = false viewModel.copyRule() } ) DropdownMenuItem( - text = { Text("粘贴规则") }, + text = { AppText("粘贴规则") }, onClick = { showMenu = false viewModel.pasteRule(onSuccess = {}) @@ -167,7 +167,7 @@ fun ReplaceEditScreen( positionProvider = TooltipDefaults.rememberTooltipPositionProvider( TooltipAnchorPosition.Above ), - tooltip = { PlainTooltip { Text("添加") } }, + tooltip = { PlainTooltip { AppText("添加") } }, state = rememberTooltipState(), ) { FloatingActionButton( @@ -214,7 +214,7 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.name, onValueChange = viewModel::onNameChange, - label = { Text("规则名称") }, + label = { AppText("规则名称") }, modifier = Modifier .fillMaxWidth() .onFocusChanged { @@ -234,8 +234,8 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.pattern, onValueChange = viewModel::onPatternChange, - label = { Text("匹配规则") }, - placeholder = { Text("输入正则表达式或关键字") }, + label = { AppText("匹配规则") }, + placeholder = { AppText("输入正则表达式或关键字") }, modifier = Modifier .fillMaxWidth() .onFocusChanged { @@ -247,8 +247,8 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.replacement, onValueChange = viewModel::onReplacementChange, - label = { Text("替换为") }, - placeholder = { Text("输入替换内容或捕获组") }, + label = { AppText("替换为") }, + placeholder = { AppText("输入替换内容或捕获组") }, modifier = Modifier .fillMaxWidth() .onFocusChanged { @@ -265,7 +265,7 @@ fun ReplaceEditScreen( FilterChip( selected = state.scopeTitle, onClick = { viewModel.onScopeTitleChange(!state.scopeTitle) }, - label = { Text("标题") }, + label = { AppText("标题") }, leadingIcon = if (state.scopeTitle) { { Icon( @@ -282,7 +282,7 @@ fun ReplaceEditScreen( FilterChip( selected = state.scopeContent, onClick = { viewModel.onScopeContentChange(!state.scopeContent) }, - label = { Text("内容") }, + label = { AppText("内容") }, leadingIcon = if (state.scopeContent) { { Icon( @@ -299,7 +299,7 @@ fun ReplaceEditScreen( FilterChip( selected = state.isRegex, onClick = { viewModel.onRegexChange(!state.isRegex) }, - label = { Text("使用正则") }, + label = { AppText("使用正则") }, leadingIcon = if (state.isRegex) { { Icon( @@ -316,8 +316,8 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.scope, onValueChange = viewModel::onScopeChange, - label = { Text("特定范围") }, - placeholder = { Text("指定规则适用的范围") }, + label = { AppText("特定范围") }, + placeholder = { AppText("指定规则适用的范围") }, modifier = Modifier .fillMaxWidth() .onFocusChanged { @@ -329,8 +329,8 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.excludeScope, onValueChange = viewModel::onExcludeScopeChange, - label = { Text("排除范围") }, - placeholder = { Text("指定规则不适用的范围") }, + label = { AppText("排除范围") }, + placeholder = { AppText("指定规则不适用的范围") }, modifier = Modifier .fillMaxWidth() .onFocusChanged { @@ -342,8 +342,8 @@ fun ReplaceEditScreen( OutlinedTextField( value = state.timeout, onValueChange = viewModel::onTimeoutChange, - label = { Text("超时 (ms)") }, - placeholder = { Text("3000") }, + label = { AppText("超时 (ms)") }, + placeholder = { AppText("3000") }, modifier = Modifier.fillMaxWidth() ) @@ -383,8 +383,8 @@ fun GroupSelector( OutlinedTextField( value = currentGroup, onValueChange = onGroupChange, - label = { Text("分组") }, - placeholder = { Text("默认") }, + label = { AppText("分组") }, + placeholder = { AppText("默认") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(), modifier = Modifier @@ -400,7 +400,7 @@ fun GroupSelector( ) { allGroups.forEach { selectionOption -> DropdownMenuItem( - text = { Text(selectionOption) }, + text = { AppText(selectionOption) }, onClick = { onGroupChange(selectionOption) expanded = false @@ -426,9 +426,9 @@ fun ManageGroupDialog( AlertDialog( onDismissRequest = onDismiss, - title = { Text("分组管理") }, + title = { AppText("分组管理") }, text = { - if (groups.isEmpty()) Text("暂无其他分组") + if (groups.isEmpty()) AppText("暂无其他分组") else Column( modifier = Modifier.verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(8.dp) @@ -448,7 +448,7 @@ fun ManageGroupDialog( verticalAlignment = Alignment.CenterVertically ) { Checkbox(checked = isSelected, onCheckedChange = null) - Text(group, Modifier.padding(start = 8.dp)) + AppText(group, Modifier.padding(start = 8.dp)) } } } @@ -462,7 +462,7 @@ fun ManageGroupDialog( text = "删除选中" ) }, - dismissButton = { TextButton(onClick = onDismiss) { Text("关闭") } } + dismissButton = { TextButton(onClick = onDismiss) { AppText("关闭") } } ) } @@ -482,7 +482,7 @@ fun QuickInputBar( symbols.forEach { symbol -> AssistChip( onClick = { onInsert(symbol) }, - label = { Text(symbol) }, + label = { AppText(symbol) }, modifier = Modifier.padding(end = 8.dp) ) } diff --git a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt index c2808857b..3cc61f0e2 100644 --- a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt +++ b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.material.icons.filled.Group import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -45,6 +44,7 @@ import io.legado.app.ui.widget.components.dialog.TextListInputDialog import io.legado.app.ui.widget.components.divider.PillDivider import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.startActivity @OptIn(ExperimentalMaterial3Api::class) @@ -133,7 +133,7 @@ fun RssFavoritesScreen( Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.Group, null, modifier = Modifier.size(18.dp)) Spacer(Modifier.width(12.dp)) - Text(stringResource(R.string.all)) + AppText(stringResource(R.string.all)) } }, onClick = { @@ -151,7 +151,7 @@ fun RssFavoritesScreen( modifier = Modifier.size(18.dp) ) Spacer(Modifier.width(12.dp)) - Text(group) + AppText(group) } }, onClick = { @@ -166,7 +166,7 @@ fun RssFavoritesScreen( Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.DeleteSweep, null, modifier = Modifier.size(18.dp)) Spacer(Modifier.width(12.dp)) - Text(stringResource(R.string.delete_select_group)) + AppText(stringResource(R.string.delete_select_group)) } }, onClick = { @@ -179,7 +179,7 @@ fun RssFavoritesScreen( Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.DeleteForever, null, modifier = Modifier.size(18.dp)) Spacer(Modifier.width(12.dp)) - Text(stringResource(R.string.all)) + AppText(stringResource(R.string.all)) } }, onClick = { @@ -248,14 +248,14 @@ fun RssFavoritesScreen( }, dropdownContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.change_group)) }, + text = { AppText(stringResource(R.string.change_group)) }, onClick = { showSetGroupDialog = rssStar dismiss() } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.delete)) }, onClick = { viewModel.deleteStar(rssStar) dismiss() diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceScreen.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceScreen.kt index 0c69d89a6..ee194858c 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceScreen.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceScreen.kt @@ -17,11 +17,9 @@ import androidx.compose.material.icons.filled.Delete import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarResult -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -43,6 +41,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.base.BaseRuleEvent import io.legado.app.data.entities.RssSource +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.DraggableSelectionHandler import io.legado.app.ui.widget.components.GroupManageBottomSheet @@ -58,6 +57,7 @@ import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.text.AppText import org.koin.androidx.compose.koinViewModel import sh.calvin.reorderable.rememberReorderableLazyListState @@ -209,8 +209,12 @@ fun RssSourceScreen( onConfirm = { viewModel.saveImportedRules() }, itemContent = { source, _ -> Column { - Text(source.sourceName, style = MaterialTheme.typography.titleMedium) - Text(source.sourceUrl, style = MaterialTheme.typography.bodySmall, maxLines = 1) + AppText(source.sourceName, style = LegadoTheme.typography.titleMedium) + AppText( + source.sourceUrl, + style = LegadoTheme.typography.bodySmall, + maxLines = 1 + ) } } ) @@ -225,16 +229,16 @@ fun RssSourceScreen( showDeleteRuleDialog?.let { source -> AlertDialog( onDismissRequest = { showDeleteRuleDialog = null }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.del_msg)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.del_msg)) }, confirmButton = { OutlinedButton(onClick = { viewModel.del(source); showDeleteRuleDialog = null - }) { Text(stringResource(R.string.ok)) } + }) { AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showDeleteRuleDialog = null }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) @@ -287,11 +291,11 @@ fun RssSourceScreen( dropDownMenuContent = { dismiss -> RoundDropdownMenuItem( onClick = { showGroupManageSheet = true }, - text = { Text("分组管理") }, + text = { AppText("分组管理") }, ) Box { RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_rss_source)) }, + text = { AppText(stringResource(R.string.import_rss_source)) }, onClick = { showImportMenu = true } ) RoundDropdownMenu( @@ -299,7 +303,7 @@ fun RssSourceScreen( onDismissRequest = { showImportMenu = false } ) { RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_on_line)) }, + text = { AppText(stringResource(R.string.import_on_line)) }, onClick = { showImportMenu = false dismiss() @@ -307,7 +311,7 @@ fun RssSourceScreen( } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_local)) }, + text = { AppText(stringResource(R.string.import_local)) }, onClick = { showImportMenu = false dismiss() @@ -315,7 +319,7 @@ fun RssSourceScreen( } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.import_default_rule)) }, + text = { AppText(stringResource(R.string.import_default_rule)) }, onClick = { showImportMenu = false dismiss() @@ -326,29 +330,29 @@ fun RssSourceScreen( } PillDivider() RoundDropdownMenuItem( - text = { Text(stringResource(R.string.all)) }, + text = { AppText(stringResource(R.string.all)) }, onClick = { dismiss(); viewModel.setGroupFilter(null) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.enabled)) }, + text = { AppText(stringResource(R.string.enabled)) }, onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_ENABLED) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.disabled)) }, + text = { AppText(stringResource(R.string.disabled)) }, onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_DISABLED) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.need_login)) }, + text = { AppText(stringResource(R.string.need_login)) }, onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_LOGIN) } ) RoundDropdownMenuItem( - text = { Text(stringResource(R.string.no_group)) }, + text = { AppText(stringResource(R.string.no_group)) }, onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_NO_GROUP) } ) PillDivider() groups.forEach { group -> RoundDropdownMenuItem( - text = { Text(group) }, + text = { AppText(group) }, onClick = { dismiss(); viewModel.setGroupFilter("${RssSourceViewModel.PREFIX_GROUP}$group") } ) } diff --git a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubScreen.kt b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubScreen.kt index 58c10ffdb..0da339c1e 100644 --- a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubScreen.kt +++ b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubScreen.kt @@ -22,11 +22,9 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.PlainTooltip import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox @@ -54,12 +52,14 @@ import io.legado.app.data.entities.RuleSubType import io.legado.app.ui.association.ImportBookSourceDialog import io.legado.app.ui.association.ImportReplaceRuleDialog import io.legado.app.ui.association.ImportRssSourceDialog +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.EmptyMessageView import io.legado.app.ui.widget.components.card.SelectionItemCard import io.legado.app.ui.widget.components.checkBox.CheckboxGroupContainer import io.legado.app.ui.widget.components.checkBox.CheckboxItem import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleListScaffold +import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.showDialogFragment import io.legado.app.utils.toastOnUi @@ -93,7 +93,7 @@ fun RuleSubScreen( Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.AutoMirrored.Filled.Sort, null, modifier = Modifier.size(18.dp)) Spacer(Modifier.size(12.dp)) - Text(stringResource(R.string.sort)) + AppText(stringResource(R.string.sort)) } }, onClick = { @@ -106,7 +106,7 @@ fun RuleSubScreen( TooltipBox( positionProvider = TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), - tooltip = { PlainTooltip { Text("Localized description") } }, + tooltip = { PlainTooltip { AppText("Localized description") } }, state = rememberTooltipState(), ) { FloatingActionButton( @@ -185,7 +185,7 @@ fun RuleSubScreen( }, dropdownContent = { dismiss -> RoundDropdownMenuItem( - text = { Text(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.delete)) }, onClick = { viewModel.delete(ruleSub) dismiss() @@ -226,24 +226,24 @@ fun RuleSubEditDialog( AlertDialog( onDismissRequest = onDismiss, - title = { Text(stringResource(R.string.rule_subscription)) }, + title = { AppText(stringResource(R.string.rule_subscription)) }, text = { Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { OutlinedTextField( value = name, onValueChange = { name = it }, - label = { Text(stringResource(R.string.name)) }, + label = { AppText(stringResource(R.string.name)) }, modifier = Modifier.fillMaxWidth() ) OutlinedTextField( value = url, onValueChange = { url = it }, - label = { Text("URL") }, + label = { AppText("URL") }, modifier = Modifier.fillMaxWidth() ) - Text( + AppText( text = "订阅类型", - style = MaterialTheme.typography.titleSmall, + style = LegadoTheme.typography.titleSmall, modifier = Modifier.padding(top = 8.dp) ) CheckboxGroupContainer(columns = 2) { @@ -265,12 +265,12 @@ fun RuleSubEditDialog( TextButton(onClick = { onConfirm(ruleSub.copy(name = name, url = url, type = type)) }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismiss) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/theme/AdaptivePadding.kt b/app/src/main/java/io/legado/app/ui/theme/AdaptivePadding.kt new file mode 100644 index 000000000..64233c4dd --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/theme/AdaptivePadding.kt @@ -0,0 +1,19 @@ +package io.legado.app.ui.theme + +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme.composeEngine + +@Composable +fun Modifier.adaptiveHorizontalPadding(): Modifier { + val horizontal = if (ThemeResolver.isMiuixEngine(composeEngine)) 12.dp else 16.dp + return this.padding(horizontal = horizontal) +} + +@Composable +fun Modifier.adaptiveVerticalPadding(): Modifier { + val horizontal = if (ThemeResolver.isMiuixEngine(composeEngine)) 12.dp else 8.dp + return this.padding(horizontal = horizontal) +} diff --git a/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt b/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt index 76a21a88a..cac926249 100644 --- a/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt +++ b/app/src/main/java/io/legado/app/ui/theme/AppTheme.kt @@ -7,9 +7,13 @@ import androidx.compose.material3.MotionScheme import androidx.compose.material3.Shapes import androidx.compose.material3.Typography import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import io.legado.app.ui.config.themeConfig.ThemeConfig +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.theme.ThemeController @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -20,29 +24,82 @@ fun AppTheme( val context = LocalContext.current val appThemeMode = ThemeResolver.resolveThemeMode(ThemeConfig.appTheme) val isPureBlack = ThemeConfig.isPureBlack - val paletteStyle = ThemeConfig.paletteStyle + val paletteStyleStr = ThemeConfig.paletteStyle val materialVersion = ThemeConfig.materialVersion + val composeEngine = ThemeConfig.composeEngine + val colorSchemeMode = ThemeResolver.resolveColorSchemeMode(ThemeConfig.themeMode) + val paletteStyle = + remember(paletteStyleStr) { ThemeResolver.resolvePaletteStyle(paletteStyleStr) } + val seedColor = remember(ThemeConfig.cPrimary) { + if (ThemeConfig.cPrimary != 0) Color(ThemeConfig.cPrimary) else Color(0xFF3482FF) + } val colorScheme = - remember(context, appThemeMode, darkTheme, isPureBlack, paletteStyle, materialVersion) { + remember(context, appThemeMode, darkTheme, isPureBlack, paletteStyleStr, materialVersion) { ThemeManager.getColorScheme( context = context, mode = appThemeMode, darkTheme = darkTheme, isAmoled = isPureBlack, - paletteStyle = paletteStyle, + paletteStyle = paletteStyleStr, materialVersion = materialVersion ) } - MaterialExpressiveTheme( - colorScheme = colorScheme, - typography = Typography(), - motionScheme = MotionScheme.expressive(), - shapes = Shapes() + val themeColors = remember(colorScheme, darkTheme, seedColor, paletteStyle, colorSchemeMode) { + LegadoThemeColors( + colorScheme = colorScheme, + isDark = darkTheme, + seedColor = seedColor, + paletteStyle = paletteStyle, + themeMode = colorSchemeMode, + useDynamicColor = appThemeMode == AppThemeMode.Dynamic, + composeEngine = composeEngine + ) + } + + CompositionLocalProvider( + LocalLegadoThemeColors provides themeColors ) { - AppBackground(darkTheme = darkTheme) { - content() + when { + ThemeResolver.isMiuixEngine(themeColors.composeEngine) -> { + val controller = remember(colorSchemeMode, darkTheme) { + ThemeController( + colorSchemeMode = colorSchemeMode, + isDark = darkTheme + ) + } + + MiuixTheme( + controller = controller + ) { + val miuixTextStyles = MiuixTheme.textStyles + val mappedTypography = remember(miuixTextStyles) { + miuixStylesToM3Typography(miuixTextStyles) + } + + CompositionLocalProvider( + LocalLegadoTypography provides mappedTypography + ) { + AppBackground(darkTheme = darkTheme) { + content() + } + } + } + } + + else -> { + MaterialExpressiveTheme( + colorScheme = colorScheme, + typography = Typography(), + motionScheme = MotionScheme.expressive(), + shapes = Shapes() + ) { + AppBackground(darkTheme = darkTheme) { + content() + } + } + } } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/theme/HazeStyle.kt b/app/src/main/java/io/legado/app/ui/theme/HazeStyle.kt index f5091207b..3fa41bc07 100644 --- a/app/src/main/java/io/legado/app/ui/theme/HazeStyle.kt +++ b/app/src/main/java/io/legado/app/ui/theme/HazeStyle.kt @@ -7,8 +7,8 @@ import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.hazeEffect import dev.chrisbanes.haze.hazeSource import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi -import dev.chrisbanes.haze.materials.HazeMaterials import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.hazeStyle.HazeLegado /** * 自动感知全局配置的 HazeSource @@ -31,9 +31,9 @@ fun Modifier.responsiveHazeEffect( if (!enableBlur) return this val style = if (enableProgressiveBlur) { - HazeMaterials.ultraThin() + HazeLegado.ultraThin() } else { - HazeMaterials.regular() + HazeLegado.regular() } return this.hazeEffect( @@ -61,6 +61,6 @@ fun Modifier.regularHazeEffect(state: HazeState): Modifier { return this.hazeEffect( state = state, - style = HazeMaterials.ultraThin() + style = HazeLegado.ultraThin() ) } diff --git a/app/src/main/java/io/legado/app/ui/theme/LegadoTheme.kt b/app/src/main/java/io/legado/app/ui/theme/LegadoTheme.kt new file mode 100644 index 000000000..292c2d277 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/theme/LegadoTheme.kt @@ -0,0 +1,85 @@ +package io.legado.app.ui.theme + +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.Typography +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color +import com.materialkolor.PaletteStyle +import dev.chrisbanes.haze.HazeState +import top.yukonga.miuix.kmp.theme.ColorSchemeMode + +data class LegadoThemeColors( + val colorScheme: ColorScheme, + val isDark: Boolean, + val seedColor: Color, + val paletteStyle: PaletteStyle, + val themeMode: ColorSchemeMode, + val useDynamicColor: Boolean, + val composeEngine: String, +) + +val LocalLegadoThemeColors = staticCompositionLocalOf { + LegadoThemeColors( + colorScheme = lightColorScheme(), + isDark = false, + seedColor = Color.Unspecified, + paletteStyle = PaletteStyle.TonalSpot, + themeMode = ColorSchemeMode.System, + useDynamicColor = true, + composeEngine = "m3" + ) +} + +val LocalLegadoTypography = staticCompositionLocalOf { + Typography() +} + +val LocalHazeState = compositionLocalOf { null } + +object LegadoTheme { + + val colorScheme: ColorScheme + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.colorScheme + + val isDark: Boolean + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.isDark + + val seedColor: Color + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.seedColor + + val paletteStyle: PaletteStyle + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.paletteStyle + + val themeMode: ColorSchemeMode + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.themeMode + + val composeEngine: String + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.composeEngine + + val useDynamicColor: Boolean + @Composable + @ReadOnlyComposable + get() = LocalLegadoThemeColors.current.useDynamicColor + + val typography: Typography + @Composable + @ReadOnlyComposable + get() = LocalLegadoTypography.current + +} diff --git a/app/src/main/java/io/legado/app/ui/theme/ThemeResolver.kt b/app/src/main/java/io/legado/app/ui/theme/ThemeResolver.kt index 9db56a725..226185e92 100644 --- a/app/src/main/java/io/legado/app/ui/theme/ThemeResolver.kt +++ b/app/src/main/java/io/legado/app/ui/theme/ThemeResolver.kt @@ -4,6 +4,7 @@ import com.materialkolor.Contrast import com.materialkolor.PaletteStyle import com.materialkolor.dynamiccolor.ColorSpec import io.legado.app.ui.config.themeConfig.ThemeConfig +import top.yukonga.miuix.kmp.theme.ColorSchemeMode object ThemeResolver { @@ -48,6 +49,17 @@ object ThemeResolver { } } + fun resolveColorSchemeMode(value: String): ColorSchemeMode = when (value) { + "0" -> ColorSchemeMode.System + "1" -> ColorSchemeMode.Light + "2" -> ColorSchemeMode.Dark + else -> ColorSchemeMode.System + } + + fun isMiuixEngine(composeEngine: String): Boolean = composeEngine == "miuix" + + fun isM3Engine(composeEngine: String): Boolean = composeEngine == "m3" + fun resolveColorSpecVersion(colorSpec: ThemeColorSpec): ColorSpec.SpecVersion { return when (colorSpec) { ThemeColorSpec.SPEC_2025 -> ColorSpec.SpecVersion.SPEC_2025 diff --git a/app/src/main/java/io/legado/app/ui/theme/Typography.kt b/app/src/main/java/io/legado/app/ui/theme/Typography.kt new file mode 100644 index 000000000..5352a507d --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/theme/Typography.kt @@ -0,0 +1,44 @@ +package io.legado.app.ui.theme + +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.Typography +import androidx.compose.ui.text.font.FontWeight +import top.yukonga.miuix.kmp.theme.TextStyles + + +/** + * 将 Miuix 的 TextStyles 语义化映射为 Material 3 的 Typography + */ + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +fun miuixStylesToM3Typography(miuixStyles: TextStyles): Typography { + return Typography( + displayLarge = miuixStyles.title1, // 32.sp + displayMedium = miuixStyles.title2, // 24.sp + displaySmall = miuixStyles.title3, // 20.sp + + headlineLarge = miuixStyles.title2, // 24.sp + headlineMedium = miuixStyles.title3, // 20.sp + headlineSmall = miuixStyles.title4, // 18.sp + + titleLarge = miuixStyles.headline1, // 17.sp + titleMedium = miuixStyles.headline2, // 16.sp + titleSmall = miuixStyles.subtitle, // 14.sp, Bold + + bodyLarge = miuixStyles.paragraph, // 17.sp, lineHeight 1.2em (如果不需要行高也可以换成 main) + bodyMedium = miuixStyles.body1, // 16.sp + bodySmall = miuixStyles.body2, // 14.sp + + labelLarge = miuixStyles.button, // 17.sp + labelMedium = miuixStyles.footnote1, // 13.sp + labelSmall = miuixStyles.footnote2, // 11.sp + + bodyLargeEmphasized = miuixStyles.paragraph.copy(fontWeight = FontWeight.Medium), + bodyMediumEmphasized = miuixStyles.body1.copy(fontWeight = FontWeight.Medium), + bodySmallEmphasized = miuixStyles.body2.copy(fontWeight = FontWeight.Medium), + + labelLargeEmphasized = miuixStyles.button.copy(fontWeight = FontWeight.Medium), + labelMediumEmphasized = miuixStyles.footnote1.copy(fontWeight = FontWeight.Medium), + labelSmallEmphasized = miuixStyles.footnote2.copy(fontWeight = FontWeight.Medium) + ) +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/theme/hazeStyle/HazeLegado.kt b/app/src/main/java/io/legado/app/ui/theme/hazeStyle/HazeLegado.kt new file mode 100644 index 000000000..20b5acb54 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/theme/hazeStyle/HazeLegado.kt @@ -0,0 +1,48 @@ +package io.legado.app.ui.theme.hazeStyle + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.unit.dp +import dev.chrisbanes.haze.HazeStyle +import dev.chrisbanes.haze.HazeTint +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.theme.MiuixTheme + +object HazeLegado { + + @Composable + @ReadOnlyComposable + fun ultraThin( + containerColor: Color = if (ThemeResolver.isMiuixEngine(composeEngine)) MiuixTheme.colorScheme.surface else MaterialTheme.colorScheme.surface, + ): HazeStyle = hazeLegado( + containerColor = containerColor, + lightAlpha = 0.35f, + darkAlpha = 0.55f, + ) + + @Composable + @ReadOnlyComposable + fun regular( + containerColor: Color = if (ThemeResolver.isMiuixEngine(composeEngine)) MiuixTheme.colorScheme.surface else MaterialTheme.colorScheme.surface, + ): HazeStyle = hazeLegado( + containerColor = containerColor, + lightAlpha = 0.73f, + darkAlpha = 0.8f, + ) + + private fun hazeLegado( + containerColor: Color, + lightAlpha: Float, + darkAlpha: Float, + ): HazeStyle = HazeStyle( + blurRadius = 24.dp, + backgroundColor = containerColor, + tint = HazeTint( + containerColor.copy(alpha = if (containerColor.luminance() >= 0.5) lightAlpha else darkAlpha), + ), + ) +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt b/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt index 292fe1b7f..70d3ec548 100644 --- a/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt +++ b/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt @@ -13,7 +13,6 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -22,6 +21,8 @@ import androidx.compose.ui.draw.rotate import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -54,9 +55,9 @@ fun CollapsibleHeader( if (titleContent != null) { titleContent() } else { - Text( + AppText( text = title, - style = MaterialTheme.typography.bodySmallEmphasized.copy( + style = LegadoTheme.typography.bodySmallEmphasized.copy( fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary ), @@ -64,9 +65,9 @@ fun CollapsibleHeader( overflow = TextOverflow.Ellipsis ) subtitle?.let { - Text( + AppText( text = it, - style = MaterialTheme.typography.labelSmallEmphasized.copy( + style = LegadoTheme.typography.labelSmallEmphasized.copy( color = MaterialTheme.colorScheme.onSurfaceVariant ), maxLines = 1, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/AnimatedText.kt b/app/src/main/java/io/legado/app/ui/widget/components/AnimatedText.kt index 1a71821d2..cfa21f308 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/AnimatedText.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/AnimatedText.kt @@ -9,7 +9,6 @@ import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -23,6 +22,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit +import io.legado.app.ui.widget.components.text.AppText @Composable fun AnimatedText( @@ -60,7 +60,7 @@ fun AnimatedText( }, label = "" ) { - Text( + AppText( style = style, color = color, softWrap = softWrap, @@ -117,7 +117,7 @@ fun AnimatedTextLine( label = "LineAnimation", modifier = modifier ) { targetText -> - Text( + AppText( text = targetText, modifier = modifier, style = style, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/AppFloatingActionButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/AppFloatingActionButton.kt new file mode 100644 index 000000000..5c72e0a93 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/AppFloatingActionButton.kt @@ -0,0 +1,56 @@ +package io.legado.app.ui.widget.components + +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.PlainTooltip +import androidx.compose.material3.TooltipAnchorPosition +import androidx.compose.material3.TooltipBox +import androidx.compose.material3.TooltipDefaults +import androidx.compose.material3.rememberTooltipState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.FloatingActionButton as MiuixFloatingActionButton + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppFloatingActionButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + tooltipText: String? = null, + content: @Composable () -> Unit +) { + val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine) + + if (isMiuix) { + MiuixFloatingActionButton( + onClick = onClick, + modifier = modifier, + content = content + ) + } else { + if (tooltipText != null) { + TooltipBox( + positionProvider = TooltipDefaults.rememberTooltipPositionProvider( + TooltipAnchorPosition.Above + ), + tooltip = { PlainTooltip { AppText(tooltipText) } }, + state = rememberTooltipState(), + ) { + FloatingActionButton( + onClick = onClick, + modifier = modifier, + content = content + ) + } + } else { + FloatingActionButton( + onClick = onClick, + modifier = modifier, + content = content + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/AppNavigationBar.kt b/app/src/main/java/io/legado/app/ui/widget/components/AppNavigationBar.kt new file mode 100644 index 000000000..eb9eda5f4 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/AppNavigationBar.kt @@ -0,0 +1,93 @@ +package io.legado.app.ui.widget.components + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.BottomAppBarDefaults +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.NavigationBarDisplayMode +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.NavigationBar as MiuixNavigationBar +import top.yukonga.miuix.kmp.basic.NavigationBarItem as MiuixNavigationBarItem + +@Composable +fun AppNavigationBar( + modifier: Modifier = Modifier, + miuixMode: NavigationBarDisplayMode = NavigationBarDisplayMode.IconAndText, + content: @Composable RowScope.() -> Unit +) { + val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine) + val opacity = (ThemeConfig.bottomBarOpacity.coerceIn(0, 100)) / 100f + + if (isMiuix) { + val baseColor = GlassDefaults.glassColor( + noBlurColor = MiuixTheme.colorScheme.surface, + blurAlpha = GlassDefaults.DefaultBlurAlpha + ) + val finalColor = baseColor.copy(alpha = (baseColor.alpha * opacity).coerceIn(0f, 1f)) + + MiuixNavigationBar( + modifier = modifier, + color = finalColor, + mode = miuixMode, + content = content + ) + } else { + val baseColor = GlassDefaults.glassColor( + noBlurColor = BottomAppBarDefaults.containerColor, + blurAlpha = GlassDefaults.DefaultBlurAlpha + ) + val finalColor = baseColor.copy(alpha = (baseColor.alpha * opacity).coerceIn(0f, 1f)) + + NavigationBar( + modifier = modifier, + containerColor = finalColor, + content = content + ) + } +} + +@Composable +fun RowScope.AppNavigationBarItem( + selected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, + labelString: String, + miuixIcon: ImageVector, + m3Icon: @Composable () -> Unit, + m3IndicatorColor: Color, + m3ShowLabel: Boolean, + m3AlwaysShowLabel: Boolean, +) { + val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine) + + if (isMiuix) { + MiuixNavigationBarItem( + selected = selected, + onClick = onClick, + icon = miuixIcon, + label = labelString, + modifier = modifier + ) + } else { + NavigationBarItem( + selected = selected, + onClick = onClick, + modifier = modifier, + icon = m3Icon, + colors = NavigationBarItemDefaults.colors(indicatorColor = m3IndicatorColor), + label = if (m3ShowLabel) { + { AppText(labelString) } + } else null, + alwaysShowLabel = m3AlwaysShowLabel + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/AppScaffold.kt b/app/src/main/java/io/legado/app/ui/widget/components/AppScaffold.kt index 696556ded..24b2dbffe 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/AppScaffold.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/AppScaffold.kt @@ -3,7 +3,6 @@ package io.legado.app.ui.widget.components import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api @@ -11,29 +10,27 @@ import androidx.compose.material3.FabPosition import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.ScaffoldDefaults -import androidx.compose.material3.TopAppBarColors -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import dev.chrisbanes.haze.HazeState import io.legado.app.ui.config.themeConfig.ThemeConfig -import io.legado.app.ui.theme.responsiveHazeEffect +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LocalHazeState +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.theme.responsiveHazeSource +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.FabPosition as MiuixFabPosition +import top.yukonga.miuix.kmp.basic.Scaffold as MiuixScaffold @OptIn(ExperimentalMaterial3Api::class) @Composable fun AppScaffold( modifier: Modifier = Modifier, - title: (@Composable () -> Unit)? = null, - subtitle: (@Composable () -> Unit)? = null, - scrollBehavior: TopAppBarScrollBehavior? = null, - navigationIcon: @Composable () -> Unit = {}, - actions: @Composable RowScope.() -> Unit = {}, - colors: TopAppBarColors = GlassTopAppBarDefaults.glassColors(), - topBar: @Composable () -> Unit = {}, + topBar: @Composable (HazeState) -> Unit = {}, bottomBar: @Composable () -> Unit = {}, snackbarHost: @Composable () -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, @@ -45,47 +42,73 @@ fun AppScaffold( val isDark = isSystemInDarkTheme() val hasImageBg = ThemeConfig.hasImageBg(isDark) val hazeState = remember { HazeState() } + val composeEngine = LegadoTheme.composeEngine val containerColor = if (hasImageBg) { Color.Transparent } else { - MaterialTheme.colorScheme.background + LegadoTheme.colorScheme.background } - val finalTopBar = @Composable { - Box(modifier = Modifier.responsiveHazeEffect(state = hazeState)) { - if (title != null) { - GlassMediumFlexibleTopAppBar( - title = title, - subtitle = subtitle, - scrollBehavior = scrollBehavior, - navigationIcon = navigationIcon, - actions = actions, - colors = colors - ) - } else { - topBar() + val miuixContainerColor = if (hasImageBg) { + Color.Transparent + } else { + MiuixTheme.colorScheme.surface + } + + CompositionLocalProvider(LocalHazeState provides hazeState) { + when { + ThemeResolver.isMiuixEngine(composeEngine) -> { + val miuixFabPosition = when (floatingActionButtonPosition) { + FabPosition.End -> MiuixFabPosition.End + FabPosition.Center -> MiuixFabPosition.Center + else -> MiuixFabPosition.End + } + MiuixScaffold( + modifier = modifier, + topBar = { + topBar(hazeState) + }, + bottomBar = bottomBar, + snackbarHost = snackbarHost, + floatingActionButton = floatingActionButton, + floatingActionButtonPosition = miuixFabPosition, + containerColor = miuixContainerColor, + contentWindowInsets = contentWindowInsets + ) { paddingValues -> + Box( + modifier = Modifier + .fillMaxSize() + .responsiveHazeSource(hazeState) + ) { + content(paddingValues) + } + } + } + + else -> { + Scaffold( + modifier = modifier, + topBar = { + topBar(hazeState) + }, + bottomBar = bottomBar, + snackbarHost = snackbarHost, + floatingActionButton = floatingActionButton, + floatingActionButtonPosition = floatingActionButtonPosition, + containerColor = containerColor, + contentColor = contentColor, + contentWindowInsets = contentWindowInsets + ) { paddingValues -> + Box( + modifier = Modifier + .fillMaxSize() + .responsiveHazeSource(hazeState) + ) { + content(paddingValues) + } + } } } } - - Scaffold( - modifier = modifier, - topBar = finalTopBar, - bottomBar = bottomBar, - snackbarHost = snackbarHost, - floatingActionButton = floatingActionButton, - floatingActionButtonPosition = floatingActionButtonPosition, - containerColor = containerColor, - contentColor = contentColor, - contentWindowInsets = contentWindowInsets - ) { paddingValues -> - Box( - modifier = Modifier - .fillMaxSize() - .responsiveHazeSource(hazeState) - ) { - content(paddingValues) - } - } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/EmptyMessageView.kt b/app/src/main/java/io/legado/app/ui/widget/components/EmptyMessageView.kt index a5de35e2d..66df4fb29 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/EmptyMessageView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/EmptyMessageView.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.ContainedLoadingIndicator import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -24,6 +23,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import io.legado.app.ui.theme.LegadoTheme @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -70,7 +70,7 @@ fun EmptyMessageView( AnimatedTextLine( text = message, - style = MaterialTheme.typography.labelLarge, + style = LegadoTheme.typography.labelLarge, textAlign = TextAlign.Center, maxLines = 2, softWrap = true, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/GlassMediumFlexibleTopAppBar.kt b/app/src/main/java/io/legado/app/ui/widget/components/GlassMediumFlexibleTopAppBar.kt deleted file mode 100644 index bd6d1432f..000000000 --- a/app/src/main/java/io/legado/app/ui/widget/components/GlassMediumFlexibleTopAppBar.kt +++ /dev/null @@ -1,113 +0,0 @@ -package io.legado.app.ui.widget.components - -import androidx.compose.foundation.layout.RowScope -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.MediumFlexibleTopAppBar -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarColors -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.TopAppBarScrollBehavior -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import io.legado.app.ui.config.themeConfig.ThemeConfig - -@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) -@Composable -fun GlassMediumFlexibleTopAppBar( - modifier: Modifier = Modifier, - title: @Composable () -> Unit, - subtitle: (@Composable () -> Unit)? = null, - scrollBehavior: TopAppBarScrollBehavior? = null, - navigationIcon: @Composable () -> Unit = {}, - actions: @Composable RowScope.() -> Unit = {}, - colors: TopAppBarColors = GlassTopAppBarDefaults.glassColors() -) { - if (ThemeConfig.useFlexibleTopAppBar) { - MediumFlexibleTopAppBar( - modifier = modifier, - title = title, - subtitle = subtitle, - navigationIcon = navigationIcon, - actions = actions, - scrollBehavior = scrollBehavior, - colors = colors - ) - } else { - TopAppBar( - modifier = modifier, - title = title, - navigationIcon = navigationIcon, - actions = actions, - scrollBehavior = scrollBehavior, - colors = colors - ) - } -} - -object GlassTopAppBarDefaults { - - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun defaultScrollBehavior(): TopAppBarScrollBehavior { - return if (ThemeConfig.useFlexibleTopAppBar) { - TopAppBarDefaults.exitUntilCollapsedScrollBehavior() - } else { - TopAppBarDefaults.pinnedScrollBehavior() - } - } - - @Composable - fun glassColors(): TopAppBarColors { - - val containerColor = GlassDefaults.glassColor( - noBlurColor = MaterialTheme.colorScheme.surface, - blurAlpha = GlassDefaults.TransparentAlpha - ) - - val scrolledContainerColor = if (ThemeConfig.enableBlur) { - MaterialTheme.colorScheme.surface.copy(alpha = GlassDefaults.TransparentAlpha) - } else { - MaterialTheme.colorScheme.surfaceContainer - } - - return TopAppBarDefaults.topAppBarColors( - containerColor = applyTopBarOpacity(containerColor), - scrolledContainerColor = applyTopBarOpacity(scrolledContainerColor) - ) - } - - @Composable - fun containerColor(): Color { - val baseColor = GlassDefaults.glassColor( - noBlurColor = MaterialTheme.colorScheme.surface, - blurAlpha = GlassDefaults.TransparentAlpha - ) - return applyTopBarOpacity(baseColor) - } - - @Composable - fun scrolledContainerColor(): Color { - val baseColor = GlassDefaults.glassColor( - noBlurColor = MaterialTheme.colorScheme.surfaceContainer, - blurAlpha = GlassDefaults.TransparentAlpha - ) - return applyTopBarOpacity(baseColor) - } - - @Composable - fun controlContainerColor(): Color { - val baseColor = GlassDefaults.glassColor( - noBlurColor = MaterialTheme.colorScheme.surfaceContainerHighest, - blurAlpha = GlassDefaults.DefaultBlurAlpha - ) - return applyTopBarOpacity(baseColor) - } - - private fun applyTopBarOpacity(color: Color): Color { - val opacity = (ThemeConfig.topBarOpacity.coerceIn(0, 100)) / 100f - return color.copy(alpha = (color.alpha * opacity).coerceIn(0f, 1f)) - } -} diff --git a/app/src/main/java/io/legado/app/ui/widget/components/GroupManageBottomSheet.kt b/app/src/main/java/io/legado/app/ui/widget/components/GroupManageBottomSheet.kt index 120e28b43..8d91e4feb 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/GroupManageBottomSheet.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/GroupManageBottomSheet.kt @@ -18,7 +18,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -31,9 +30,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.button.SmallTextButton import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet import io.legado.app.ui.widget.components.settingItem.SettingItem +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -52,10 +53,10 @@ fun GroupManageBottomSheet( .padding(bottom = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Text( + AppText( modifier = Modifier.padding(bottom = 16.dp), text = stringResource(R.string.group_manage), - style = MaterialTheme.typography.titleMedium + style = LegadoTheme.typography.titleMedium ) LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) { items(groups, key = { it }) { group -> @@ -115,7 +116,7 @@ private fun GroupItem( modifier = Modifier .fillMaxWidth() .heightIn(min = 48.dp), - label = { Text(stringResource(R.string.edit)) }, + label = { AppText(stringResource(R.string.edit)) }, contentPadding = PaddingValues( top = 4.dp, bottom = 4.dp, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/IconSwitch.kt b/app/src/main/java/io/legado/app/ui/widget/components/IconSwitch.kt index 305d58fa7..c34eb4fef 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/IconSwitch.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/IconSwitch.kt @@ -10,6 +10,40 @@ import androidx.compose.material3.SwitchDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.basic.Switch as MiuixSwitch + +@Composable +fun AdaptiveSwitch( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + checkedIcon: ImageVector = Icons.Filled.Check, + uncheckedIcon: ImageVector? = null, + showIcon: Boolean = true +) { + val composeEngine = LegadoTheme.composeEngine + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixSwitch( + checked = checked, + onCheckedChange = onCheckedChange, + modifier = modifier, + enabled = enabled + ) + } else { + IconSwitch( + checked = checked, + onCheckedChange = onCheckedChange, + enabled = enabled, + checkedIcon = checkedIcon, + uncheckedIcon = uncheckedIcon, + showIcon = showIcon + ) + } +} @Composable fun IconSwitch( diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt b/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt index f1ffd61c5..d62ac9726 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt @@ -26,7 +26,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable @@ -43,6 +42,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import io.legado.app.ui.widget.components.button.SmallIconButton +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -104,7 +104,7 @@ fun SearchBarSection( .fillMaxWidth() .heightIn(min = 48.dp) .padding(horizontal = 4.dp), - placeholder = { Text(placeholder) }, + placeholder = { AppText(placeholder) }, leadingIcon = leadingIcon, trailingIcon = { Row( diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SelectionBottomBar.kt b/app/src/main/java/io/legado/app/ui/widget/components/SelectionBottomBar.kt index 0f3b2da5e..953ee3b0f 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/SelectionBottomBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/SelectionBottomBar.kt @@ -15,7 +15,6 @@ import androidx.compose.material3.HorizontalFloatingToolbar import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.PlainTooltip -import androidx.compose.material3.Text import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox import androidx.compose.material3.TooltipDefaults @@ -27,6 +26,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import io.legado.app.ui.widget.components.text.AppText data class SelectionActions( val primaryAction: ActionItem, @@ -84,7 +84,7 @@ fun SelectionBottomBar( ) { secondaryActions.forEach { action -> DropdownMenuItem( - text = { Text(action.text) }, + text = { AppText(action.text) }, leadingIcon = action.icon, onClick = { action.onClick() @@ -101,7 +101,7 @@ fun SelectionBottomBar( positionProvider = TooltipDefaults.rememberTooltipPositionProvider( TooltipAnchorPosition.Above ), - tooltip = { PlainTooltip { Text(primaryAction.text) } }, + tooltip = { PlainTooltip { AppText(primaryAction.text) } }, state = rememberTooltipState(), ) { FilledIconButton( diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SplicedColumnGroup.kt b/app/src/main/java/io/legado/app/ui/widget/components/SplicedColumnGroup.kt index 739d4e0a4..0157b5aac 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/SplicedColumnGroup.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/SplicedColumnGroup.kt @@ -7,14 +7,14 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.title.AdaptiveTitle +import top.yukonga.miuix.kmp.basic.Card as MiuixCard /** * Settings Group Container by https://github.com/wxxsfxyzm/InstallerX-Revived @@ -29,24 +29,33 @@ fun SplicedColumnGroup( title: String = "", content: @Composable ColumnScope.() -> Unit, ) { - Column(modifier = modifier.padding(top = 8.dp, bottom = 16.dp)) { + val composeEngine = LegadoTheme.composeEngine + Column(modifier = modifier.padding(top = 8.dp, bottom = 8.dp)) { if (title.isNotEmpty()) { - Text( + AdaptiveTitle( text = title, - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.primary, modifier = Modifier.padding(start = 16.dp, bottom = 8.dp) ) } - Card( - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = Color.Transparent), - modifier = Modifier - .fillMaxWidth() - .animateContentSize() - ) { + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixCard { + Column( + modifier = Modifier + .fillMaxWidth() + .animateContentSize() + .clip(RoundedCornerShape(16.dp)) + ) { + content() + } + } + + } else { Column( + modifier = Modifier + .fillMaxWidth() + .animateContentSize() + .clip(RoundedCornerShape(16.dp)), verticalArrangement = Arrangement.spacedBy(2.dp) ) { content() diff --git a/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkEditSheet.kt b/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkEditSheet.kt index 2e0b12866..832f97f4a 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkEditSheet.kt @@ -15,7 +15,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -26,7 +25,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import io.legado.app.data.entities.Bookmark +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -50,16 +51,16 @@ fun BookmarkEditSheet( .padding(16.dp) .navigationBarsPadding() ) { - Text( + AppText( text = bookmark.chapterName, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.padding(bottom = 16.dp) ) OutlinedTextField( value = bookText, onValueChange = { bookText = it }, - label = { Text("原文") }, + label = { AppText("原文") }, modifier = Modifier.fillMaxWidth(), maxLines = 10 ) @@ -69,7 +70,7 @@ fun BookmarkEditSheet( OutlinedTextField( value = content, onValueChange = { content = it }, - label = { Text("摘要/笔记") }, + label = { AppText("摘要/笔记") }, modifier = Modifier.fillMaxWidth(), maxLines = 5 ) @@ -86,7 +87,7 @@ fun BookmarkEditSheet( colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error), modifier = Modifier.weight(1f) ) { - Text("删除") + AppText("删除") } Button( @@ -99,7 +100,7 @@ fun BookmarkEditSheet( }, modifier = Modifier.weight(1f) ) { - Text("保存") + AppText("保存") } } Spacer(modifier = Modifier.height(16.dp)) @@ -109,8 +110,8 @@ fun BookmarkEditSheet( if (showDeleteConfirmDialog) { AlertDialog( onDismissRequest = { showDeleteConfirmDialog = false }, - title = { Text("确认删除") }, - text = { Text("你确定要删除这条书签吗?") }, + title = { AppText("确认删除") }, + text = { AppText("你确定要删除这条书签吗?") }, confirmButton = { TextButton( onClick = { @@ -119,14 +120,14 @@ fun BookmarkEditSheet( }, colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error) ) { - Text("删除") + AppText("删除") } }, dismissButton = { TextButton( onClick = { showDeleteConfirmDialog = false } ) { - Text("取消") + AppText("取消") } } ) diff --git a/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkItem.kt index aeb9f423a..cab80e10f 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/bookmark/BookmarkItem.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier @@ -19,6 +18,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.legado.app.data.entities.Bookmark +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -49,17 +50,17 @@ fun BookmarkItem( .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp) ) { - Text( + AppText( text = bookmark.chapterName, - style = MaterialTheme.typography.titleSmallEmphasized, + style = LegadoTheme.typography.titleSmallEmphasized, color = if (isDur) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary ) if (bookmark.bookText.isNotEmpty()) { Spacer(modifier = Modifier.height(4.dp)) - Text( + AppText( text = bookmark.bookText, - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, maxLines = 2, overflow = TextOverflow.Ellipsis, color = MaterialTheme.colorScheme.onSurfaceVariant @@ -68,9 +69,9 @@ fun BookmarkItem( if (bookmark.content.isNotEmpty()) { Spacer(modifier = Modifier.height(2.dp)) - Text( + AppText( text = bookmark.content, - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.primary ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/AlertButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/AlertButton.kt index e6f18d3fb..fd97db5a7 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/AlertButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/AlertButton.kt @@ -3,10 +3,10 @@ package io.legado.app.ui.widget.components.button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import io.legado.app.ui.widget.components.text.AppText @Composable fun AlertButton( @@ -24,6 +24,6 @@ fun AlertButton( containerColor = Color.Transparent, ) ) { - Text(text = text) + AppText(text = text) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedActionButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedActionButton.kt index 261984e98..5b93a9c81 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedActionButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedActionButton.kt @@ -8,8 +8,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.ToggleButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -21,6 +19,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.delay @OptIn(ExperimentalMaterial3ExpressiveApi::class) @@ -73,9 +73,9 @@ fun AnimatedActionButton( AnimatedVisibility( visible = showText ) { - Text( + AppText( text = if (lastCheckedState) activeText else inactiveText, - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, modifier = Modifier.padding(start = 8.dp), maxLines = 1, softWrap = false diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedTextButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedTextButton.kt index b2df9fc52..e0bd24c2e 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedTextButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedTextButton.kt @@ -8,11 +8,11 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith import androidx.compose.material3.ContainedLoadingIndicator import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -38,7 +38,7 @@ fun AnimatedTextButton( if (loading) { ContainedLoadingIndicator() } else { - Text(text) + AppText(text) } } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/MiuixBackButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/MiuixBackButton.kt new file mode 100644 index 000000000..27093ad7e --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/MiuixBackButton.kt @@ -0,0 +1,57 @@ +package io.legado.app.ui.widget.components.button + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import io.legado.app.R +import top.yukonga.miuix.kmp.basic.Icon +import top.yukonga.miuix.kmp.basic.IconButton +import top.yukonga.miuix.kmp.icon.MiuixIcons +import top.yukonga.miuix.kmp.icon.extended.Back +import top.yukonga.miuix.kmp.theme.LocalContentColor +import top.yukonga.miuix.kmp.theme.MiuixTheme + +@Composable +fun MiuixButton( + modifier: Modifier = Modifier, + imageVector: ImageVector = MiuixIcons.Regular.Back, + tint: Color = LocalContentColor.current, + contentDescription: String? = stringResource(id = R.string.back), + onClick: () -> Unit, +) { + IconButton( + onClick = onClick, + modifier = modifier + ) { + Icon( + imageVector = imageVector, + contentDescription = contentDescription, + tint = tint + ) + } +} + +@Composable +fun MiuixToggleButton( + modifier: Modifier = Modifier, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + iconChecked: ImageVector, + iconUnchecked: ImageVector = iconChecked, + checkedTint: Color = MiuixTheme.colorScheme.primary, + uncheckedTint: Color = LocalContentColor.current, + contentDescription: String? = null, +) { + IconButton( + onClick = { onCheckedChange(!checked) }, + modifier = modifier + ) { + Icon( + imageVector = if (checked) iconChecked else iconUnchecked, + contentDescription = contentDescription, + tint = if (checked) checkedTint else uncheckedTint + ) + } +} diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/SmallIconButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/SmallIconButton.kt index 99bfe8f41..6d1a51ad0 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/SmallIconButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/SmallIconButton.kt @@ -15,11 +15,9 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.IconToggleButtonShapes import androidx.compose.material3.LocalMinimumInteractiveComponentSize -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedIconButton import androidx.compose.material3.OutlinedIconToggleButton import androidx.compose.material3.OutlinedToggleButton -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -31,7 +29,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.delay +import top.yukonga.miuix.kmp.basic.Icon as MiuixIcon +import top.yukonga.miuix.kmp.basic.IconButton as MiuixIconButton @OptIn(ExperimentalMaterial3ExpressiveApi::class) @@ -41,22 +45,33 @@ fun SmallIconButton( icon: ImageVector, contentDescription: String? = null ) { - CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) { - IconButton( - onClick = onClick, - modifier = Modifier.size( - IconButtonDefaults.extraSmallContainerSize( - IconButtonDefaults.IconButtonWidthOption.Uniform - ) - ), - shape = IconButtonDefaults.extraSmallRoundShape, + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixIconButton( + onClick = onClick ) { - Icon( + MiuixIcon( imageVector = icon, - contentDescription = contentDescription, - modifier = Modifier.size(IconButtonDefaults.extraSmallIconSize), + contentDescription = contentDescription ) } + } else { + CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) { + IconButton( + onClick = onClick, + modifier = Modifier.size( + IconButtonDefaults.extraSmallContainerSize( + IconButtonDefaults.IconButtonWidthOption.Uniform + ) + ), + shape = IconButtonDefaults.extraSmallRoundShape, + ) { + Icon( + imageVector = icon, + contentDescription = contentDescription, + modifier = Modifier.size(IconButtonDefaults.extraSmallIconSize), + ) + } + } } } @@ -204,9 +219,9 @@ fun SmallAnimatedActionButton( AnimatedVisibility( visible = showText ) { - Text( + AppText( text = if (lastCheckedState) activeText else inactiveText, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, modifier = Modifier.padding(start = 6.dp), maxLines = 1, softWrap = false diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/SmallTextButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/SmallTextButton.kt index e26cd9f38..4dc24e991 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/SmallTextButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/SmallTextButton.kt @@ -6,12 +6,13 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText @Composable fun SmallTextButton( @@ -32,9 +33,9 @@ fun SmallTextButton( modifier = Modifier.size(16.dp) ) Spacer(Modifier.width(4.dp)) - Text( + AppText( text = text, - style = MaterialTheme.typography.labelMedium + style = LegadoTheme.typography.labelMedium ) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/button/TopBarButton.kt b/app/src/main/java/io/legado/app/ui/widget/components/button/TopBarButton.kt index d7c3e822d..f6251874d 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/button/TopBarButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/button/TopBarButton.kt @@ -22,7 +22,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedIconButton -import androidx.compose.material3.Text import androidx.compose.material3.ToggleButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -35,7 +34,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import io.legado.app.ui.config.themeConfig.ThemeConfig -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import kotlinx.coroutines.delay enum class TopBarButtonVariant { @@ -109,13 +111,22 @@ fun TopbarNavigationButton( contentDescription: String? = "返回", style: TopBarButtonVariant = TopBarButtonVariant.Filled ) { - TopBarButton( - onClick = onClick, - imageVector = imageVector, - contentDescription = contentDescription, - modifier = modifier.padding(horizontal = 12.dp), - style = style - ) + if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) { + MiuixButton( + onClick = onClick, + imageVector = imageVector, + contentDescription = contentDescription, + modifier = modifier.padding(horizontal = 16.dp) + ) + } else { + TopBarButton( + onClick = onClick, + imageVector = imageVector, + contentDescription = contentDescription, + modifier = modifier.padding(horizontal = 12.dp), + style = style + ) + } } @Composable @@ -126,21 +137,29 @@ fun TopBarActionButton( modifier: Modifier = Modifier ) { val enableProgressive = ThemeConfig.enableProgressiveBlur - - if (enableProgressive) { - TopBarButton( + if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) { + MiuixButton( onClick = onClick, imageVector = imageVector, contentDescription = contentDescription, - modifier = modifier.padding(end = 12.dp), - style = TopBarButtonVariant.Filled + modifier = modifier.padding(end = 8.dp), ) } else { - IconButton(onClick = onClick) { - Icon( + if (enableProgressive) { + TopBarButton( + onClick = onClick, imageVector = imageVector, - contentDescription = contentDescription + contentDescription = contentDescription, + modifier = modifier.padding(end = 12.dp), + style = TopBarButtonVariant.Filled ) + } else { + IconButton(onClick = onClick) { + Icon( + imageVector = imageVector, + contentDescription = contentDescription + ) + } } } } @@ -165,43 +184,51 @@ fun TopBarAnimatedActionButton( showText = false } } - - ToggleButton( - modifier = modifier.height(36.dp), - contentPadding = PaddingValues(horizontal = 8.dp), - checked = checked, - onCheckedChange = { - lastCheckedState = it - onCheckedChange(it) - showText = true - } - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ) { - - AnimatedContent( - targetState = checked, - label = "IconAnimation" - ) { targetChecked -> - AnimatedIcon( - modifier = Modifier.size(20.dp), - imageVector = if (targetChecked) iconChecked else iconUnchecked, - contentDescription = null - ) + if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) { + MiuixToggleButton( + checked = checked, + onCheckedChange = onCheckedChange, + iconChecked = iconChecked, + iconUnchecked = iconUnchecked + ) + } else { + ToggleButton( + modifier = modifier.height(36.dp), + contentPadding = PaddingValues(horizontal = 8.dp), + checked = checked, + onCheckedChange = { + lastCheckedState = it + onCheckedChange(it) + showText = true } - - AnimatedVisibility( - visible = showText + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center ) { - Text( - text = if (lastCheckedState) activeText else inactiveText, - style = MaterialTheme.typography.labelMedium, - modifier = Modifier.padding(start = 8.dp), - maxLines = 1, - softWrap = false - ) + + AnimatedContent( + targetState = checked, + label = "IconAnimation" + ) { targetChecked -> + AnimatedIcon( + modifier = Modifier.size(20.dp), + imageVector = if (targetChecked) iconChecked else iconUnchecked, + contentDescription = null + ) + } + + AnimatedVisibility( + visible = showText + ) { + AppText( + text = if (lastCheckedState) activeText else inactiveText, + style = LegadoTheme.typography.labelMedium, + modifier = Modifier.padding(start = 8.dp), + maxLines = 1, + softWrap = false + ) + } } } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/card/GlassCard.kt b/app/src/main/java/io/legado/app/ui/widget/components/card/GlassCard.kt index 43de6eedf..e8b781948 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/card/GlassCard.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/card/GlassCard.kt @@ -4,14 +4,79 @@ import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.ColumnScope import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.Card -import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardElevation import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.Card as MiuixCard +import top.yukonga.miuix.kmp.basic.CardDefaults as MiuixCardDefaults + +@OptIn(ExperimentalMaterialApi::class) +@Composable +private fun BaseCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = CardDefaults.shape, + cornerRadius: Dp = MiuixCardDefaults.CornerRadius, + containerColor: Color? = null, + contentColor: Color? = null, + elevation: CardElevation = CardDefaults.cardElevation(), + border: BorderStroke? = null, + alpha: Float = 1f, + content: @Composable ColumnScope.() -> Unit +) { + if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) { + val colors = MiuixCardDefaults.defaultColors( + color = (containerColor + ?: MiuixTheme.colorScheme.secondaryContainer).copy(alpha = alpha), + contentColor = contentColor ?: MiuixTheme.colorScheme.onSurface + ) + MiuixCard( + modifier = modifier, + cornerRadius = cornerRadius, + onClick = onClick, + content = content, + colors = colors + ) + } else { + val colors = CardDefaults.cardColors( + containerColor = (containerColor ?: MaterialTheme.colorScheme.secondaryContainer).copy( + alpha = alpha + ), + contentColor = contentColor ?: MaterialTheme.colorScheme.onSecondaryContainer, + disabledContainerColor = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = alpha * 0.38f), + disabledContentColor = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = alpha * 0.38f) + ) + if (onClick != null) { + Card( + modifier = modifier, + shape = shape, + colors = colors, + elevation = elevation, + border = border, + onClick = onClick, + content = content + ) + } else { + Card( + modifier = modifier, + shape = shape, + colors = colors, + elevation = elevation, + border = border, + content = content + ) + } + } +} @OptIn(ExperimentalMaterialApi::class) @Composable @@ -19,43 +84,50 @@ fun GlassCard( modifier: Modifier = Modifier, onClick: (() -> Unit)? = null, shape: Shape = CardDefaults.shape, - colors: CardColors? = null, + cornerRadius: Dp = MiuixCardDefaults.CornerRadius, + containerColor: Color? = null, + contentColor: Color? = null, elevation: CardElevation = CardDefaults.cardElevation(), border: BorderStroke? = null, content: @Composable ColumnScope.() -> Unit ) { - val containerAlpha = ThemeConfig.containerOpacity / 100f + BaseCard( + modifier = modifier, + onClick = onClick, + shape = shape, + cornerRadius = cornerRadius, + containerColor = containerColor, + contentColor = contentColor, + elevation = elevation, + border = border, + alpha = ThemeConfig.containerOpacity / 100f, + content = content + ) +} - val baseColors = colors ?: CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer, - contentColor = MaterialTheme.colorScheme.onSecondaryContainer +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun NormalCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = CardDefaults.shape, + cornerRadius: Dp = MiuixCardDefaults.CornerRadius, + containerColor: Color? = null, + contentColor: Color? = null, + elevation: CardElevation = CardDefaults.cardElevation(), + border: BorderStroke? = null, + content: @Composable ColumnScope.() -> Unit +) { + BaseCard( + modifier = modifier, + onClick = onClick, + shape = shape, + cornerRadius = cornerRadius, + containerColor = containerColor, + contentColor = contentColor, + elevation = elevation, + border = border, + alpha = 1f, + content = content ) - - val finalColors = CardDefaults.cardColors( - containerColor = baseColors.containerColor.copy(alpha = containerAlpha), - contentColor = baseColors.contentColor, - disabledContainerColor = baseColors.disabledContainerColor.copy(alpha = containerAlpha), - disabledContentColor = baseColors.disabledContentColor - ) - - if (onClick != null) { - Card( - onClick = onClick, - modifier = modifier, - shape = shape, - colors = finalColors, - elevation = elevation, - border = border, - content = content - ) - } else { - Card( - modifier = modifier, - shape = shape, - colors = finalColors, - elevation = elevation, - border = border, - content = content - ) - } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/card/SelectionItemCard.kt b/app/src/main/java/io/legado/app/ui/widget/components/card/SelectionItemCard.kt index 14373157c..f8db95733 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/card/SelectionItemCard.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/card/SelectionItemCard.kt @@ -24,8 +24,6 @@ import androidx.compose.material3.Checkbox import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Switch -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -41,10 +39,17 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.AdaptiveSwitch import io.legado.app.ui.widget.components.button.SmallIconButton import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu +import io.legado.app.ui.widget.components.text.AppText import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableLazyListState +import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.theme.MiuixTheme @Composable fun SelectionItemCard( @@ -66,11 +71,14 @@ fun SelectionItemCard( ) { var showMenu by remember { mutableStateOf(false) } + val composeEngine = ThemeResolver.isMiuixEngine(composeEngine) val animatedContainerColor by animateColorAsState( targetValue = if (isSelected) - selectedContainerColor ?: MaterialTheme.colorScheme.secondaryContainer + selectedContainerColor + ?: if (composeEngine) MiuixTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.secondaryContainer else - containerColor ?: MaterialTheme.colorScheme.surfaceContainerLow, + containerColor + ?: if (composeEngine) MiuixTheme.colorScheme.surfaceContainer else MaterialTheme.colorScheme.surfaceContainerLow, animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing), label = "CardColor" ) @@ -81,7 +89,7 @@ fun SelectionItemCard( .padding(horizontal = 16.dp) .fillMaxWidth(), shape = MaterialTheme.shapes.medium, - colors = CardDefaults.cardColors(containerColor = animatedContainerColor), + containerColor = animatedContainerColor, elevation = CardDefaults.cardElevation(defaultElevation = elevation) ) { Row( @@ -113,28 +121,49 @@ fun SelectionItemCard( } } - ListItem( - modifier = Modifier.weight(1f), - headlineContent = { - Text( + if (composeEngine) { + BasicComponent( + modifier = Modifier.weight(1f) + ) { + AppText( text = title, - style = MaterialTheme.typography.titleSmall, + style = LegadoTheme.typography.titleSmall, maxLines = 1, overflow = TextOverflow.Ellipsis ) - }, - supportingContent = if (!subtitle.isNullOrBlank()) { - { - Text( + if (!subtitle.isNullOrBlank()) { + AppText( text = subtitle, - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis ) } - } else null, - colors = ListItemDefaults.colors(containerColor = Color.Transparent) - ) + } + } else { + ListItem( + modifier = Modifier.weight(1f), + headlineContent = { + AppText( + text = title, + style = LegadoTheme.typography.titleSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + supportingContent = if (!subtitle.isNullOrBlank()) { + { + AppText( + text = subtitle, + style = LegadoTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } else null, + colors = ListItemDefaults.colors(containerColor = Color.Transparent) + ) + } Row( verticalAlignment = Alignment.CenterVertically, @@ -143,7 +172,7 @@ fun SelectionItemCard( .padding(end = 8.dp) ) { onEnabledChange?.let { - Switch( + AdaptiveSwitch( modifier = Modifier.scale(0.8f), checked = isEnabled, onCheckedChange = it diff --git a/app/src/main/java/io/legado/app/ui/widget/components/card/SettingCard.kt b/app/src/main/java/io/legado/app/ui/widget/components/card/SettingCard.kt new file mode 100644 index 000000000..bc4953351 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/card/SettingCard.kt @@ -0,0 +1,75 @@ +package io.legado.app.ui.widget.components.card + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material3.Card +import androidx.compose.material3.CardColors +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CardElevation +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.basic.BasicComponent + +// import top.yukonga.miuix.kmp.basic.theme.LocalColors as MiuixLocalColors + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun SettingCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = CardDefaults.shape, + colors: CardColors? = null, + elevation: CardElevation = CardDefaults.cardElevation(), + border: BorderStroke? = null, + content: @Composable ColumnScope.() -> Unit +) { + val composeEngine = LegadoTheme.composeEngine + val containerAlpha = ThemeConfig.containerOpacity / 100f + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + BasicComponent( + modifier = modifier, + onClick = onClick, + content = content + ) + } else { + val baseColors = colors ?: CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer + ) + + val finalColors = CardDefaults.cardColors( + containerColor = baseColors.containerColor.copy(alpha = containerAlpha), + contentColor = baseColors.contentColor, + disabledContainerColor = baseColors.disabledContainerColor.copy(alpha = containerAlpha), + disabledContentColor = baseColors.disabledContentColor + ) + + if (onClick != null) { + Card( + onClick = onClick, + modifier = modifier, + shape = shape, + colors = finalColors, + elevation = elevation, + border = border, + content = content + ) + } else { + Card( + modifier = modifier, + shape = shape, + colors = finalColors, + elevation = elevation, + border = border, + content = content + ) + } + } +} diff --git a/app/src/main/java/io/legado/app/ui/widget/components/card/TextCard.kt b/app/src/main/java/io/legado/app/ui/widget/components/card/TextCard.kt index cacfc9f1e..86abfd33c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/card/TextCard.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/card/TextCard.kt @@ -6,50 +6,42 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AnimatedTextLine -@Preview(showBackground = true) -@Composable -fun PreviewTextCard() { - MaterialTheme { - TextCard( - text = "v1.0.0" - ) - } -} +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun TextCard( modifier: Modifier = Modifier, text: String, icon: ImageVector? = null, onClick: (() -> Unit)? = null, - backgroundColor: Color = colorScheme.primaryContainer, - contentColor: Color = colorScheme.onPrimaryContainer, + backgroundColor: Color = MaterialTheme.colorScheme.primaryContainer, + contentColor: Color = MaterialTheme.colorScheme.onPrimaryContainer, cornerRadius: Dp = 8.dp, horizontalPadding: Dp = 8.dp, verticalPadding: Dp = 2.dp, iconSize: Dp = 14.dp, spacing: Dp = 4.dp, - textStyle: TextStyle = MaterialTheme.typography.labelSmall + textStyle: TextStyle = LegadoTheme.typography.labelSmallEmphasized ) { - GlassCard( + NormalCard( modifier = modifier, shape = RoundedCornerShape(cornerRadius), - colors = CardDefaults.cardColors(containerColor = backgroundColor), + containerColor = backgroundColor, + contentColor = contentColor, onClick = onClick ) { Row( diff --git a/app/src/main/java/io/legado/app/ui/widget/components/checkBox/CheckboxItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/checkBox/CheckboxItem.kt index f341faed5..1bfb8c85d 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/checkBox/CheckboxItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/checkBox/CheckboxItem.kt @@ -7,7 +7,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Checkbox import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import io.legado.app.ui.widget.components.text.AppText import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -15,6 +15,7 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme @Composable fun CheckboxItem( @@ -45,9 +46,9 @@ fun CheckboxItem( enabled = enabled, modifier = Modifier.alpha(alpha) ) - Text( + AppText( text = title, - style = MaterialTheme.typography.bodyMedium, + style = LegadoTheme.typography.bodyMedium, maxLines = 1, modifier = Modifier .padding(start = 12.dp) diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt b/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt index ed6817b86..ec7f0be47 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt @@ -13,7 +13,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.card.TextCard +import top.yukonga.miuix.kmp.theme.MiuixTheme @Composable fun BookshelfCover( @@ -27,6 +31,16 @@ fun BookshelfCover( sourceOrigin: String? = null, onLoadFinish: (() -> Unit)? = null ) { + val backgroundColor = if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixTheme.colorScheme.primaryContainer.copy(alpha = 0.2f) + } else { + MaterialTheme.colorScheme.secondaryContainer + } + val contentColor = if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.onSecondaryContainer + } Box(modifier = modifier) { BookCover( name = name, @@ -44,8 +58,8 @@ fun BookshelfCover( modifier = Modifier .align(Alignment.TopEnd) .padding(2.dp), - backgroundColor = MaterialTheme.colorScheme.secondaryContainer, - contentColor = MaterialTheme.colorScheme.onSecondaryContainer, + backgroundColor = backgroundColor, + contentColor = contentColor, cornerRadius = 4.dp, horizontalPadding = 4.dp, verticalPadding = 0.dp @@ -59,8 +73,8 @@ fun BookshelfCover( .fillMaxWidth() .padding(horizontal = 4.dp, vertical = 6.dp) .height(3.dp), - color = MaterialTheme.colorScheme.primary, - trackColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), + color = LegadoTheme.colorScheme.primary, + trackColor = LegadoTheme.colorScheme.primary.copy(alpha = 0.2f), strokeCap = StrokeCap.Round ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/dialog/ColorPickerSheet.kt b/app/src/main/java/io/legado/app/ui/widget/components/dialog/ColorPickerSheet.kt index 0c124e227..26390c39c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/dialog/ColorPickerSheet.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/dialog/ColorPickerSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -41,7 +40,9 @@ import com.github.skydoves.colorpicker.compose.BrightnessSlider import com.github.skydoves.colorpicker.compose.HsvColorPicker import com.github.skydoves.colorpicker.compose.rememberColorPickerController import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -86,9 +87,9 @@ fun ColorPickerSheet( .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Text( + AppText( text = "颜色选择", - style = MaterialTheme.typography.titleLarge, + style = LegadoTheme.typography.titleLarge, modifier = Modifier.padding(bottom = 16.dp) ) @@ -168,9 +169,9 @@ fun ColorPickerSheet( ) ) Spacer(modifier = Modifier.width(12.dp)) - Text( + AppText( text = "#${Integer.toHexString(currentColor.toArgb()).uppercase()}", - style = MaterialTheme.typography.bodyLarge + style = LegadoTheme.typography.bodyLarge ) Row( @@ -178,14 +179,14 @@ fun ColorPickerSheet( horizontalArrangement = Arrangement.End ) { TextButton(onClick = onDismissRequest) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } Spacer(modifier = Modifier.width(8.dp)) Button(onClick = { onColorSelected(currentColor.toArgb()) onDismissRequest() }) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/dialog/TextListInputDialog.kt b/app/src/main/java/io/legado/app/ui/widget/components/dialog/TextListInputDialog.kt index 1444facbf..1bb7fddd9 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/dialog/TextListInputDialog.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/dialog/TextListInputDialog.kt @@ -10,9 +10,7 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.material3.AlertDialog import androidx.compose.material3.AssistChip -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -22,6 +20,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText @Composable fun TextListInputDialog( @@ -36,22 +36,22 @@ fun TextListInputDialog( AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(title) }, + title = { AppText(title) }, text = { Column { OutlinedTextField( value = text, onValueChange = { text = it }, - label = { Text(hint) }, + label = { AppText(hint) }, modifier = Modifier.fillMaxWidth(), singleLine = true ) if (suggestions.isNotEmpty()) { Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = "建议:", - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, modifier = Modifier.padding(bottom = 4.dp) ) LazyRow( @@ -61,7 +61,7 @@ fun TextListInputDialog( items(suggestions) { suggestion -> AssistChip( onClick = { text = suggestion }, - label = { Text(suggestion) } + label = { AppText(suggestion) } ) } } @@ -72,12 +72,12 @@ fun TextListInputDialog( TextButton( onClick = { onConfirm(text) } ) { - Text(stringResource(android.R.string.ok)) + AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/widget/components/divider/PillHeaderDivider.kt b/app/src/main/java/io/legado/app/ui/widget/components/divider/PillHeaderDivider.kt index f44574dc0..e189ed31c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/divider/PillHeaderDivider.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/divider/PillHeaderDivider.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -17,6 +16,8 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.text.AppText @Composable fun PillHeaderDivider( @@ -40,9 +41,9 @@ fun PillHeaderDivider( .background(dotColor) ) - Text( + AppText( text = title, - style = MaterialTheme.typography.labelSmall, + style = LegadoTheme.typography.labelSmall, color = titleColor, modifier = Modifier.padding(horizontal = 12.dp), maxLines = 1 diff --git a/app/src/main/java/io/legado/app/ui/widget/components/filePicker/FilePickerSheet.kt b/app/src/main/java/io/legado/app/ui/widget/components/filePicker/FilePickerSheet.kt index 735069bba..0ed751d4d 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/filePicker/FilePickerSheet.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/filePicker/FilePickerSheet.kt @@ -20,7 +20,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -28,7 +27,9 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText enum class FilePickerSheetMode { DIR, FILE, EXPORT @@ -56,9 +57,9 @@ fun FilePickerSheet( .padding(horizontal = 16.dp, vertical = 8.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Text( + AppText( text = title, - style = MaterialTheme.typography.titleMedium, + style = LegadoTheme.typography.titleMedium, modifier = Modifier.padding(bottom = 20.dp) ) @@ -141,9 +142,9 @@ private fun RowScope.FilePickerOptionCard( tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.height(8.dp)) - Text( + AppText( text = text, - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, maxLines = 1 ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/heatmap/HeatmapCalendarComponents.kt b/app/src/main/java/io/legado/app/ui/widget/components/heatmap/HeatmapCalendarComponents.kt index 20815a1e3..8c75dac87 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/heatmap/HeatmapCalendarComponents.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/heatmap/HeatmapCalendarComponents.kt @@ -25,7 +25,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedIconButton -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -41,7 +40,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.button.AnimatedActionButton +import io.legado.app.ui.widget.components.text.AppText import java.time.LocalDate /** @@ -60,7 +61,7 @@ fun HeatmapCalendarTopBar( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text("时间线", style = MaterialTheme.typography.titleMedium) + AppText("时间线", style = LegadoTheme.typography.titleMedium) Row(verticalAlignment = Alignment.CenterVertically) { AnimatedActionButton( @@ -107,7 +108,7 @@ fun WeekdayLabelsColumn( labels.forEachIndexed { index, label -> if (index % 2 == 0) { - Text( + AppText( text = label, fontSize = 10.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, @@ -170,7 +171,7 @@ fun NoEarlierDataIndicator( verticalArrangement = Arrangement.Center ) { "没有更早数据".forEach { char -> - Text( + AppText( text = char.toString(), fontSize = 9.sp, lineHeight = 12.sp, @@ -252,7 +253,7 @@ fun HeatmapWeekColumn( // 月份标签 if (firstDayOfMonth != null) { - Text( + AppText( text = "${firstDayOfMonth.monthValue}月", fontSize = 10.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, @@ -280,9 +281,9 @@ fun HeatmapLegend( ) { val legendUnit = if (mode == HeatmapMode.COUNT) "次" else "长" - Text( + AppText( "少($legendUnit)", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = Color.Gray ) @@ -298,9 +299,9 @@ fun HeatmapLegend( Spacer(modifier = Modifier.width(4.dp)) } - Text( + AppText( "多($legendUnit)", - style = MaterialTheme.typography.bodySmall, + style = LegadoTheme.typography.bodySmall, color = Color.Gray ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/icon/AppIcon.kt b/app/src/main/java/io/legado/app/ui/widget/components/icon/AppIcon.kt new file mode 100644 index 000000000..a2f0270e2 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/icon/AppIcon.kt @@ -0,0 +1,37 @@ +package io.legado.app.ui.widget.components.icon + +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.theme.LocalContentColor +import top.yukonga.miuix.kmp.basic.Icon as MiuixIcon + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun AppIcon( + imageVector: ImageVector, + contentDescription: String?, + modifier: Modifier = Modifier, + tint: Color = LocalContentColor.current, +) { + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixIcon( + imageVector = imageVector, + contentDescription = contentDescription, + modifier = modifier, + tint = tint + ) + } else { + Icon( + imageVector = imageVector, + contentDescription = contentDescription, + modifier = modifier, + tint = tint + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/importComponents/ImportComponents.kt b/app/src/main/java/io/legado/app/ui/widget/components/importComponents/ImportComponents.kt index 18caaf8f1..2c72a0c8e 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/importComponents/ImportComponents.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/importComponents/ImportComponents.kt @@ -42,7 +42,6 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedToggleButton import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberModalBottomSheetState @@ -59,9 +58,11 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AnimatedText import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.launch @Composable @@ -77,25 +78,25 @@ fun SourceInputDialog( AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(title) }, + title = { AppText(title) }, text = { Column { OutlinedTextField( value = text, onValueChange = { text = it }, - label = { Text(hint) }, + label = { AppText(hint) }, modifier = Modifier.fillMaxWidth(), maxLines = 5 ) if (historyValues.isNotEmpty()) { Spacer(modifier = Modifier.height(8.dp)) - Text("历史记录:", style = MaterialTheme.typography.labelSmall) + AppText("历史记录:", style = LegadoTheme.typography.labelSmall) LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) { items(historyValues) { history -> AssistChip( onClick = { text = history }, - label = { Text(history, maxLines = 1) } + label = { AppText(history, maxLines = 1) } ) } } @@ -105,11 +106,11 @@ fun SourceInputDialog( confirmButton = { OutlinedButton( onClick = { if (text.isNotBlank()) onConfirm(text) } - ) { Text(stringResource(android.R.string.ok)) } + ) { AppText(stringResource(android.R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(stringResource(android.R.string.cancel)) + AppText(stringResource(android.R.string.cancel)) } } ) @@ -254,14 +255,14 @@ private fun ImportItemRow( ) }, supportingContent = { - Text( + AppText( text = when (status) { ImportStatus.New -> "新增" ImportStatus.Update -> "更新" ImportStatus.Existing -> "已有" ImportStatus.Error -> "错误" }, - style = MaterialTheme.typography.labelMedium, + style = LegadoTheme.typography.labelMedium, color = when (status) { ImportStatus.New -> MaterialTheme.colorScheme.primary ImportStatus.Update -> MaterialTheme.colorScheme.secondary @@ -315,12 +316,12 @@ fun ImportBottomBar( ) } Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - OutlinedButton(onClick = onCancel) { Text("取消") } + OutlinedButton(onClick = onCancel) { AppText("取消") } Button( enabled = selectedCount > 0, onClick = onConfirm ) { - Text("导入") + AppText("导入") } } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/list/ListScaffold.kt b/app/src/main/java/io/legado/app/ui/widget/components/list/ListScaffold.kt index de0e53644..e1805234b 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/list/ListScaffold.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/list/ListScaffold.kt @@ -15,19 +15,11 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset import androidx.compose.material3.Icon -import androidx.compose.material3.PlainTooltip import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.material3.TooltipAnchorPosition -import androidx.compose.material3.TooltipBox -import androidx.compose.material3.TooltipDefaults -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.animateFloatingActionButton -import androidx.compose.material3.rememberTooltipState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -35,11 +27,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import io.legado.app.ui.widget.components.AppFloatingActionButton import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SelectionActions import io.legado.app.ui.widget.components.SelectionBottomBar import io.legado.app.ui.widget.components.topbar.DynamicTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarScrollBehavior @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -52,28 +46,21 @@ fun ListScaffold( onSearchQueryChange: (String) -> Unit, searchPlaceholder: String = "搜索...", topBarActions: @Composable RowScope.() -> Unit = {}, - bottomContent: @Composable (ColumnScope.(TopAppBarScrollBehavior) -> Unit)? = null, + bottomContent: @Composable (ColumnScope.(GlassTopAppBarScrollBehavior) -> Unit)? = null, dropDownMenuContent: @Composable (ColumnScope.(dismiss: () -> Unit) -> Unit)? = null, selectionActions: SelectionActions? = null, onAddClick: (() -> Unit)? = null, floatingActionButton: @Composable () -> Unit = { onAddClick?.let { onClick -> - TooltipBox( - positionProvider = TooltipDefaults.rememberTooltipPositionProvider( - TooltipAnchorPosition.Above + AppFloatingActionButton( + onClick = onClick, + modifier = Modifier.animateFloatingActionButton( + visible = state.selectedIds.isEmpty(), + alignment = Alignment.BottomEnd, ), - tooltip = { PlainTooltip { Text("添加") } }, - state = rememberTooltipState(), + tooltipText = "添加" ) { - FloatingActionButton( - modifier = Modifier.animateFloatingActionButton( - visible = state.selectedIds.isEmpty(), - alignment = Alignment.BottomEnd, - ), - onClick = onClick - ) { - Icon(Icons.Default.Add, contentDescription = "Add") - } + Icon(Icons.Default.Add, contentDescription = "Add") } } }, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/menuItem/RoundDropdownMenuItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/menuItem/RoundDropdownMenuItem.kt index 560b6b4d7..8e20a0531 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/menuItem/RoundDropdownMenuItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/menuItem/RoundDropdownMenuItem.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.rememberOpaqueColorScheme @Composable @@ -57,7 +58,7 @@ fun RoundDropdownMenuItem( ) { CompositionLocalProvider( LocalContentColor provides contentColor, - LocalTextStyle provides MaterialTheme.typography.labelLarge + LocalTextStyle provides LegadoTheme.typography.labelLarge ) { Row( modifier = Modifier diff --git a/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleEditSheet.kt b/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleEditSheet.kt index 0a528c2ea..e2cb8063a 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleEditSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -37,6 +36,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet +import io.legado.app.ui.widget.components.text.AppText import kotlinx.coroutines.launch /** @@ -84,7 +84,7 @@ fun RuleEditSheet( .verticalScroll(rememberScrollState()) ) { CenterAlignedTopAppBar( - title = { Text(title) }, + title = { AppText(title) }, navigationIcon = { IconButton(onClick = onDismissRequest) { Icon( @@ -99,7 +99,7 @@ fun RuleEditSheet( } DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) { DropdownMenuItem( - text = { Text(stringResource(R.string.copy_rule)) }, + text = { AppText(stringResource(R.string.copy_rule)) }, leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) }, onClick = { onCopy(getCurrentEntity()) @@ -107,7 +107,7 @@ fun RuleEditSheet( } ) DropdownMenuItem( - text = { Text(stringResource(R.string.paste_rule)) }, + text = { AppText(stringResource(R.string.paste_rule)) }, leadingIcon = { Icon(Icons.Default.ContentPaste, null) }, onClick = { scope.launch { @@ -136,20 +136,20 @@ fun RuleEditSheet( modifier = Modifier.fillMaxWidth(), value = name, onValueChange = { name = it }, - label = { Text(stringResource(R.string.name)) }, + label = { AppText(stringResource(R.string.name)) }, singleLine = true ) OutlinedTextField( modifier = Modifier.fillMaxWidth(), value = rule1, onValueChange = { rule1 = it }, - label = { Text(label1) } + label = { AppText(label1) } ) OutlinedTextField( modifier = Modifier.fillMaxWidth(), value = rule2, onValueChange = { rule2 = it }, - label = { Text(label2) }, + label = { AppText(label2) }, minLines = 3 ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleListScaffold.kt b/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleListScaffold.kt index 78931b93d..48b588124 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleListScaffold.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/rules/RuleListScaffold.kt @@ -10,20 +10,12 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.PlainTooltip import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.TooltipAnchorPosition -import androidx.compose.material3.TooltipBox -import androidx.compose.material3.TooltipDefaults -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.animateFloatingActionButton -import androidx.compose.material3.rememberTooltipState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -34,9 +26,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import io.legado.app.R import io.legado.app.ui.widget.components.ActionItem +import io.legado.app.ui.widget.components.AppFloatingActionButton import io.legado.app.ui.widget.components.SelectionActions import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.list.ListUiState +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarScrollBehavior @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -49,7 +44,7 @@ fun RuleListScaffold( onSearchQueryChange: (String) -> Unit, searchPlaceholder: String = "搜索...", topBarActions: @Composable RowScope.() -> Unit = {}, - bottomContent: @Composable (ColumnScope.(TopAppBarScrollBehavior) -> Unit)? = null, + bottomContent: @Composable (ColumnScope.(GlassTopAppBarScrollBehavior) -> Unit)? = null, dropDownMenuContent: (@Composable ColumnScope.(dismiss: () -> Unit) -> Unit)? = null, onClearSelection: () -> Unit, onSelectAll: () -> Unit, @@ -59,22 +54,15 @@ fun RuleListScaffold( onAddClick: (() -> Unit)? = null, floatingActionButton: @Composable () -> Unit = { onAddClick?.let { onClick -> - TooltipBox( - positionProvider = TooltipDefaults.rememberTooltipPositionProvider( - TooltipAnchorPosition.Above + AppFloatingActionButton( + onClick = onClick, + modifier = Modifier.animateFloatingActionButton( + visible = state.selectedIds.isEmpty(), + alignment = Alignment.BottomEnd, ), - tooltip = { PlainTooltip { Text("添加") } }, - state = rememberTooltipState(), + tooltipText = "添加" ) { - FloatingActionButton( - modifier = Modifier.animateFloatingActionButton( - visible = state.selectedIds.isEmpty(), - alignment = Alignment.BottomEnd, - ), - onClick = onClick - ) { - Icon(Icons.Default.Add, contentDescription = "Add") - } + Icon(Icons.Default.Add, contentDescription = "Add") } } }, @@ -86,8 +74,8 @@ fun RuleListScaffold( if (showDeleteConfirmDialog) { AlertDialog( onDismissRequest = { showDeleteConfirmDialog = false }, - title = { Text(stringResource(R.string.delete)) }, - text = { Text(stringResource(R.string.del_msg)) }, + title = { AppText(stringResource(R.string.delete)) }, + text = { AppText(stringResource(R.string.del_msg)) }, confirmButton = { OutlinedButton( onClick = { @@ -98,12 +86,12 @@ fun RuleListScaffold( contentColor = MaterialTheme.colorScheme.error ) ) { - Text(stringResource(R.string.ok)) + AppText(stringResource(R.string.ok)) } }, dismissButton = { TextButton(onClick = { showDeleteConfirmDialog = false }) { - Text(stringResource(R.string.cancel)) + AppText(stringResource(R.string.cancel)) } } ) diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ClickableSettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ClickableSettingItem.kt index cb77972a6..219d6dfa6 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ClickableSettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ClickableSettingItem.kt @@ -7,6 +7,10 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.basic.BasicComponentDefaults +import top.yukonga.miuix.kmp.extra.SuperArrow @Composable fun ClickableSettingItem( @@ -19,20 +23,30 @@ fun ClickableSettingItem( trailingContent: (@Composable () -> Unit)? = null, onClick: () -> Unit ) { - SettingItem( - modifier = modifier, - title = title, - description = description, - option = option, - imageVector = imageVector, - trailingContent = trailingContent ?: { - Icon( - imageVector = Icons.Default.ChevronRight, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) - }, - onClick = onClick, - onLongClick = onLongClick - ) + val composeEngine = LegadoTheme.composeEngine + if (ThemeResolver.isMiuixEngine(composeEngine)) { + SuperArrow( + title = title, + summary = description, + insideMargin = BasicComponentDefaults.InsideMargin, + onClick = onClick + ) + } else { + SettingItem( + modifier = modifier, + title = title, + description = description, + option = option, + imageVector = imageVector, + trailingContent = trailingContent ?: { + Icon( + imageVector = Icons.Default.ChevronRight, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + }, + onClick = onClick, + onLongClick = onLongClick + ) + } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/CompactSettingItems.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/CompactSettingItems.kt index dd360dfa8..e5e83b6f6 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/CompactSettingItems.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/CompactSettingItems.kt @@ -13,7 +13,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider import androidx.compose.material3.Switch -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -31,6 +30,7 @@ import androidx.compose.ui.unit.dp import io.legado.app.ui.widget.components.button.SmallOutlinedIconButton import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -66,7 +66,7 @@ fun CompactDropdownSettingItem( dropdownMenu = { onDismiss -> displayEntries.forEachIndexed { index, display -> RoundDropdownMenuItem( - text = { Text(display) }, + text = { AppText(display) }, onClick = { onValueChange(entryValues[index]) onDismiss() diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/InputSettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/InputSettingItem.kt index a6b62e88e..63ad5d893 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/InputSettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/InputSettingItem.kt @@ -1,15 +1,17 @@ package io.legado.app.ui.widget.components.settingItem +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Replay -import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -21,7 +23,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.button.SmallTextButton +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.basic.TextField as MiuixTextField @Composable fun InputSettingItem( @@ -31,6 +38,7 @@ fun InputSettingItem( description: String? = null, onConfirm: (String) -> Unit ) { + // 1. 状态统一提升到外部,两套引擎共用 var expanded by remember { mutableStateOf(false) } val state = rememberTextFieldState(initialText = value) @@ -42,51 +50,104 @@ fun InputSettingItem( } } - SettingItem( - title = title, - description = description, - option = value, - expanded = expanded, - onExpandChange = { expanded = it }, - expandContent = { - TextField( - state = state, - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 48.dp), - label = { Text(stringResource(R.string.edit)) }, - contentPadding = PaddingValues( - top = 4.dp, - bottom = 4.dp, - start = 12.dp, - end = 12.dp - ), - onKeyboardAction = { - onConfirm(state.text.toString()) - expanded = false - } + val composeEngine = LegadoTheme.composeEngine + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + Column(modifier = Modifier.fillMaxWidth()) { + BasicComponent( + title = title, + summary = value, + onClick = { expanded = !expanded } ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End - ) { - SmallTextButton( - text = "默认", - icon = Icons.Default.Replay, - onClick = { - state.edit { replace(0, length, defaultValue.toString()) } + AnimatedVisibility(visible = expanded) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 4.dp) + ) { + MiuixTextField( + state = state, + modifier = Modifier.fillMaxWidth(), + label = stringResource(R.string.edit), + onKeyboardAction = { + onConfirm(state.text.toString()) + expanded = false + } + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp), + horizontalArrangement = Arrangement.End + ) { + SmallTextButton( + text = "默认", + icon = Icons.Default.Replay, + onClick = { + state.edit { replace(0, length, defaultValue.toString()) } + } + ) + SmallTextButton( + text = "确认", + icon = Icons.Default.Check, + onClick = { + onConfirm(state.text.toString()) + expanded = false + } + ) } - ) - SmallTextButton( - text = "确认", - icon = Icons.Default.Check, - onClick = { + } + } + } + } else { + SettingItem( + title = title, + description = description, + option = value, + expanded = expanded, + onExpandChange = { expanded = it }, + expandContent = { + TextField( + state = state, + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 48.dp), + label = { AppText(stringResource(R.string.edit)) }, + contentPadding = PaddingValues( + top = 4.dp, + bottom = 4.dp, + start = 12.dp, + end = 12.dp + ), + onKeyboardAction = { onConfirm(state.text.toString()) expanded = false } ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + SmallTextButton( + text = "默认", + icon = Icons.Default.Replay, + onClick = { + state.edit { replace(0, length, defaultValue.toString()) } + } + ) + SmallTextButton( + text = "确认", + icon = Icons.Default.Check, + onClick = { + onConfirm(state.text.toString()) + expanded = false + } + ) + } } - } - ) + ) + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ListSettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ListSettingItem.kt index 724b40289..532302557 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ListSettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/ListSettingItem.kt @@ -4,12 +4,16 @@ import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.material3.Icon -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.SpinnerEntry +import top.yukonga.miuix.kmp.extra.SuperSpinner @Composable fun DropdownListSettingItem( @@ -21,33 +25,62 @@ fun DropdownListSettingItem( imageVector: ImageVector? = null, onValueChange: (String) -> Unit ) { - val currentEntry = displayEntries.getOrNull(entryValues.indexOf(selectedValue)) ?: selectedValue + val composeEngine = LegadoTheme.composeEngine - SettingItem( - title = title, - description = description, - option = currentEntry, - imageVector = imageVector, - onClick = { }, - dropdownMenu = { onDismiss -> - displayEntries.forEachIndexed { index, display -> - RoundDropdownMenuItem( - text = { Text(display) }, - onClick = { - onValueChange(entryValues[index]) - onDismiss() - }, - trailingIcon = if (selectedValue == entryValues[index]) { - { - Icon( - Icons.Default.Check, - contentDescription = null, - modifier = Modifier.size(18.dp) - ) - } - } else null - ) - } + if (ThemeResolver.isMiuixEngine(composeEngine)) { + val selectedIndex = entryValues.indexOf(selectedValue).coerceAtLeast(0) + val spinnerItems = displayEntries.map { display -> + SpinnerEntry(title = display) } - ) + + SuperSpinner( + title = title, + summary = description, + items = spinnerItems, + selectedIndex = selectedIndex, + startAction = imageVector?.let { icon -> + { + Icon( + imageVector = icon, + contentDescription = null + ) + } + }, + onSelectedIndexChange = { index -> + onValueChange(entryValues[index]) + } + ) + } else { + + val currentEntry = + displayEntries.getOrNull(entryValues.indexOf(selectedValue)) ?: selectedValue + + SettingItem( + title = title, + description = description, + option = currentEntry, + imageVector = imageVector, + onClick = { }, + dropdownMenu = { onDismiss -> + displayEntries.forEachIndexed { index, display -> + RoundDropdownMenuItem( + text = { AppText(display) }, + onClick = { + onValueChange(entryValues[index]) + onDismiss() + }, + trailingIcon = if (selectedValue == entryValues[index]) { + { + Icon( + Icons.Default.Check, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + } + } else null + ) + } + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SettingItem.kt index 727a075e1..884239099 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SettingItem.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults 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 @@ -33,8 +32,10 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp -import io.legado.app.ui.widget.components.card.GlassCard +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.card.SettingCard import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu +import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -59,7 +60,7 @@ fun SettingItem( var showMenu by remember { mutableStateOf(false) } val isExpandable = expandContent != null && onExpandChange != null - GlassCard( + SettingCard( modifier = modifier .fillMaxWidth(), shape = shape, @@ -101,25 +102,25 @@ fun SettingItem( } } else null, headlineContent = { - Text( + AppText( text = title, - style = MaterialTheme.typography.titleMedium + style = LegadoTheme.typography.titleMedium ) }, supportingContent = if (description != null || option != null) { { Column(verticalArrangement = Arrangement.spacedBy(2.dp)) { description?.let { - Text( + AppText( it, - style = MaterialTheme.typography.bodySmallEmphasized, + style = LegadoTheme.typography.bodySmallEmphasized, color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) ) } option?.let { - Text( + AppText( it, - style = MaterialTheme.typography.labelMediumEmphasized, + style = LegadoTheme.typography.labelMediumEmphasized, color = MaterialTheme.colorScheme.primary ) } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SliderSettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SliderSettingItem.kt index d1f3a5b39..a1a08a3ad 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SliderSettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SliderSettingItem.kt @@ -1,12 +1,15 @@ package io.legado.app.ui.widget.components.settingItem import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.TextFieldLineLimits @@ -17,7 +20,6 @@ import androidx.compose.material.icons.filled.LinearScale import androidx.compose.material.icons.filled.RestartAlt import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider -import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -29,7 +31,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.widget.components.button.SmallTextButton +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.basic.Slider as MiuixSlider +import top.yukonga.miuix.kmp.basic.TextField as MiuixTextField @Composable fun SliderSettingItem( @@ -45,85 +53,188 @@ fun SliderSettingItem( var expanded by remember { mutableStateOf(false) } var isInputMode by remember { mutableStateOf(false) } - var inputText by remember { mutableStateOf(value.toInt().toString()) } val textFieldState = rememberTextFieldState(initialText = value.toInt().toString()) - SettingItem( - title = title, - color = color ?: MaterialTheme.colorScheme.surfaceContainerLow, - option = description, - expanded = expanded, - onExpandChange = { expanded = it }, - expandContent = { - Row(verticalAlignment = Alignment.CenterVertically) { - AnimatedContent( - targetState = isInputMode, - label = "input_slider_switch" - ) { targetInputMode -> - if (targetInputMode) { - TextField( - state = textFieldState, - lineLimits = TextFieldLineLimits.SingleLine, - label = { Text("输入数值 (${valueRange.start.toInt()}-${valueRange.endInclusive.toInt()})") }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 48.dp), - contentPadding = PaddingValues( - top = 4.dp, - bottom = 4.dp, - start = 12.dp, - end = 12.dp - ), - inputTransformation = { - val newText = asCharSequence().toString() - newText.toFloatOrNull()?.let { num -> - onValueChange( - num.coerceIn( - valueRange.start, - valueRange.endInclusive + if (ThemeResolver.isMiuixEngine(composeEngine)) { + + Column(modifier = Modifier.fillMaxWidth()) { + BasicComponent( + title = title, + summary = description, + onClick = { expanded = !expanded } + ) + + AnimatedVisibility(visible = expanded) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + AnimatedContent( + targetState = isInputMode, + label = "input_slider_switch" + ) { targetInputMode -> + if (targetInputMode) { + MiuixTextField( + state = textFieldState, + lineLimits = TextFieldLineLimits.SingleLine, + label = "输入数值 (${valueRange.start.toInt()}-${valueRange.endInclusive.toInt()})", + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.fillMaxWidth(), + inputTransformation = { + val newText = asCharSequence().toString() + newText.toFloatOrNull()?.let { num -> + onValueChange( + num.coerceIn( + valueRange.start, + valueRange.endInclusive + ) ) + } + } + ) + } else { + MiuixSlider( + value = value, + onValueChange = { + onValueChange(it) + textFieldState.edit { + replace( + 0, + length, + it.toInt().toString() + ) + } + }, + valueRange = valueRange, + steps = steps, + modifier = Modifier.fillMaxWidth() + ) + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + horizontalArrangement = Arrangement.End + ) { + SmallTextButton( + text = if (isInputMode) "滑块" else "输入", + icon = if (isInputMode) Icons.Default.LinearScale else Icons.Default.Edit, + onClick = { isInputMode = !isInputMode } + ) + + Spacer(Modifier.width(8.dp)) + + SmallTextButton( + text = "默认", + icon = Icons.Default.RestartAlt, + onClick = { + onValueChange(defaultValue) + textFieldState.edit { + replace( + 0, + length, + defaultValue.toInt().toString() ) } } ) - } else { - Slider( - value = value, - onValueChange = { - onValueChange(it) - textFieldState.edit { replace(0, length, it.toInt().toString()) } - }, - valueRange = valueRange, - steps = steps, - modifier = Modifier - .fillMaxWidth() - ) } } } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End - ) { - SmallTextButton( - text = if (isInputMode) "滑块" else "输入", - icon = if (isInputMode) Icons.Default.LinearScale else Icons.Default.Edit, - onClick = { isInputMode = !isInputMode } - ) - - Spacer(Modifier.width(8.dp)) - - SmallTextButton( - text = "默认", - icon = Icons.Default.RestartAlt, - onClick = { - onValueChange(defaultValue) - textFieldState.edit { replace(0, length, defaultValue.toInt().toString()) } - } - ) - } } - ) + + } else { + SettingItem( + title = title, + color = color ?: MaterialTheme.colorScheme.surfaceContainerLow, + option = description, + expanded = expanded, + onExpandChange = { expanded = it }, + expandContent = { + Row(verticalAlignment = Alignment.CenterVertically) { + AnimatedContent( + targetState = isInputMode, + label = "input_slider_switch" + ) { targetInputMode -> + if (targetInputMode) { + TextField( + state = textFieldState, + lineLimits = TextFieldLineLimits.SingleLine, + label = { AppText("输入数值 (${valueRange.start.toInt()}-${valueRange.endInclusive.toInt()})") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 48.dp), + contentPadding = PaddingValues( + top = 4.dp, + bottom = 4.dp, + start = 12.dp, + end = 12.dp + ), + inputTransformation = { + val newText = asCharSequence().toString() + newText.toFloatOrNull()?.let { num -> + onValueChange( + num.coerceIn( + valueRange.start, + valueRange.endInclusive + ) + ) + } + } + ) + } else { + Slider( + value = value, + onValueChange = { + onValueChange(it) + textFieldState.edit { + replace( + 0, + length, + it.toInt().toString() + ) + } + }, + valueRange = valueRange, + steps = steps, + modifier = Modifier.fillMaxWidth() + ) + } + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + SmallTextButton( + text = if (isInputMode) "滑块" else "输入", + icon = if (isInputMode) Icons.Default.LinearScale else Icons.Default.Edit, + onClick = { isInputMode = !isInputMode } + ) + + Spacer(Modifier.width(8.dp)) + + SmallTextButton( + text = "默认", + icon = Icons.Default.RestartAlt, + onClick = { + onValueChange(defaultValue) + textFieldState.edit { + replace( + 0, + length, + defaultValue.toInt().toString() + ) + } + } + ) + } + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SwitchSettingItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SwitchSettingItem.kt index 09a3d33bf..f0e458f20 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SwitchSettingItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/settingItem/SwitchSettingItem.kt @@ -3,7 +3,12 @@ package io.legado.app.ui.widget.components.settingItem import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import io.legado.app.ui.widget.components.IconSwitch +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.AdaptiveSwitch +import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.basic.Switch + @Composable fun SwitchSettingItem( @@ -15,18 +20,40 @@ fun SwitchSettingItem( enabled: Boolean = true, onCheckedChange: (Boolean) -> Unit ) { - SettingItem( - title = title, - description = description, - imageVector = imageVector, - color = color, - onClick = { if (enabled) onCheckedChange(!checked) }, - trailingContent = { - IconSwitch( - checked = checked, - onCheckedChange = onCheckedChange, - enabled = enabled - ) + val composeEngine = LegadoTheme.composeEngine + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + val toggleAction = { + if (enabled) onCheckedChange(!checked) } - ) + + BasicComponent( + title = title, + summary = description, + enabled = enabled, + onClick = toggleAction, + endActions = { + Switch( + checked = checked, + onCheckedChange = onCheckedChange, + enabled = enabled + ) + } + ) + } else { + SettingItem( + title = title, + description = description, + imageVector = imageVector, + color = color, + onClick = { if (enabled) onCheckedChange(!checked) }, + trailingContent = { + AdaptiveSwitch( + checked = checked, + onCheckedChange = onCheckedChange, + enabled = enabled + ) + } + ) + } } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AdaptiveTabRow.kt b/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AdaptiveTabRow.kt new file mode 100644 index 000000000..c9afdf567 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AdaptiveTabRow.kt @@ -0,0 +1,63 @@ +package io.legado.app.ui.widget.components.tabRow + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.PrimaryScrollableTabRow +import androidx.compose.material3.Tab +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.widget.components.text.AppText +import top.yukonga.miuix.kmp.basic.TabRowDefaults +import top.yukonga.miuix.kmp.basic.TabRowWithContour + +@Composable +fun AdaptiveTabRow( + tabTitles: List, + selectedTabIndex: Int, + onTabSelected: (Int) -> Unit, + modifier: Modifier = Modifier +) { + val composeEngine = LegadoTheme.composeEngine + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + TabRowWithContour( + tabs = tabTitles, + selectedTabIndex = selectedTabIndex, + onTabSelected = onTabSelected, + modifier = modifier.padding(start = 12.dp), + colors = TabRowDefaults.tabRowColors( + backgroundColor = Color.Transparent + ) + ) + } else { + PrimaryScrollableTabRow( + selectedTabIndex = selectedTabIndex, + edgePadding = 0.dp, + divider = { }, + containerColor = Color.Transparent, + minTabWidth = 0.dp, + modifier = modifier + ) { + tabTitles.forEachIndexed { index, title -> + Tab( + selected = selectedTabIndex == index, + onClick = { onTabSelected(index) }, + text = { + AppText( + text = title, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(horizontal = 8.dp), + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/text/AppText.kt b/app/src/main/java/io/legado/app/ui/widget/components/text/AppText.kt new file mode 100644 index 000000000..51a1735e5 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/text/AppText.kt @@ -0,0 +1,150 @@ +package io.legado.app.ui.widget.components.text + + +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.TextUnit +import io.legado.app.ui.theme.LegadoTheme.composeEngine +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.Text as MiuixText + +@Composable +fun AppText( + text: String, + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + fontSize: TextUnit = TextUnit.Unspecified, + fontStyle: FontStyle? = null, + fontWeight: FontWeight? = null, + fontFamily: FontFamily? = null, + letterSpacing: TextUnit = TextUnit.Unspecified, + textDecoration: TextDecoration? = null, + textAlign: TextAlign? = null, + lineHeight: TextUnit = TextUnit.Unspecified, + overflow: TextOverflow = TextOverflow.Clip, + softWrap: Boolean = true, + maxLines: Int = Int.MAX_VALUE, + minLines: Int = 1, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, + style: TextStyle? = null, +) { + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixText( + text = text, + modifier = modifier, + color = color, + fontSize = fontSize, + fontStyle = fontStyle, + fontWeight = fontWeight, + fontFamily = fontFamily, + letterSpacing = letterSpacing, + textDecoration = textDecoration, + textAlign = textAlign, + lineHeight = lineHeight, + overflow = overflow, + softWrap = softWrap, + maxLines = maxLines, + minLines = minLines, + onTextLayout = onTextLayout, + style = style ?: MiuixTheme.textStyles.main + ) + } else { + Text( + text = text, + modifier = modifier, + color = color, + fontSize = fontSize, + fontStyle = fontStyle, + fontWeight = fontWeight, + fontFamily = fontFamily, + letterSpacing = letterSpacing, + textDecoration = textDecoration, + textAlign = textAlign, + lineHeight = lineHeight, + overflow = overflow, + softWrap = softWrap, + maxLines = maxLines, + minLines = minLines, + onTextLayout = onTextLayout ?: {}, + style = style ?: LocalTextStyle.current + ) + } +} + +@Composable +fun AppText( + text: AnnotatedString, + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + fontSize: TextUnit = TextUnit.Unspecified, + fontStyle: FontStyle? = null, + fontWeight: FontWeight? = null, + fontFamily: FontFamily? = null, + letterSpacing: TextUnit = TextUnit.Unspecified, + textDecoration: TextDecoration? = null, + textAlign: TextAlign? = null, + lineHeight: TextUnit = TextUnit.Unspecified, + overflow: TextOverflow = TextOverflow.Clip, + softWrap: Boolean = true, + maxLines: Int = Int.MAX_VALUE, + minLines: Int = 1, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, + style: TextStyle? = null, +) { + + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixText( + text = text, + modifier = modifier, + color = color, + fontSize = fontSize, + fontStyle = fontStyle, + fontWeight = fontWeight, + fontFamily = fontFamily, + letterSpacing = letterSpacing, + textDecoration = textDecoration, + textAlign = textAlign, + lineHeight = lineHeight, + overflow = overflow, + softWrap = softWrap, + maxLines = maxLines, + minLines = minLines, + onTextLayout = onTextLayout ?: {}, + style = style ?: MiuixTheme.textStyles.main + ) + } else { + Text( + text = text, + modifier = modifier, + color = color, + fontSize = fontSize, + fontStyle = fontStyle, + fontWeight = fontWeight, + fontFamily = fontFamily, + letterSpacing = letterSpacing, + textDecoration = textDecoration, + textAlign = textAlign, + lineHeight = lineHeight, + overflow = overflow, + softWrap = softWrap, + maxLines = maxLines, + minLines = minLines, + onTextLayout = onTextLayout ?: {}, + style = style ?: LocalTextStyle.current + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/title/SmallTitle.kt b/app/src/main/java/io/legado/app/ui/widget/components/title/SmallTitle.kt new file mode 100644 index 000000000..b6f5f4fa8 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/title/SmallTitle.kt @@ -0,0 +1,33 @@ +package io.legado.app.ui.widget.components.title + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.ThemeResolver +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.Text as MiuixText + +@Composable +fun AdaptiveTitle( + text: String, + modifier: Modifier = Modifier +) { + val composeEngine = LegadoTheme.composeEngine + if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixText( + modifier = modifier, + text = text, + style = MiuixTheme.textStyles.subtitle, + color = MiuixTheme.colorScheme.onBackgroundVariant, + ) + } else { + Text( + text = text, + style = LegadoTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.primary, + modifier = modifier + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/topbar/DynamicTopAppBar.kt b/app/src/main/java/io/legado/app/ui/widget/components/topbar/DynamicTopAppBar.kt index dca7f7d9a..1d4048933 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/topbar/DynamicTopAppBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/topbar/DynamicTopAppBar.kt @@ -1,14 +1,12 @@ package io.legado.app.ui.widget.components.topbar import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.animateColorAsState import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth @@ -20,8 +18,8 @@ import androidx.compose.material.icons.filled.Search import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -30,11 +28,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.lerp import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.style.TextOverflow -import io.legado.app.ui.widget.components.AdaptiveAnimatedText import io.legado.app.ui.widget.components.AnimatedTextLine -import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.GlassTopAppBarDefaults import io.legado.app.ui.widget.components.SearchBarSection import io.legado.app.ui.widget.components.button.TopBarActionButton import io.legado.app.ui.widget.components.button.TopbarNavigationButton @@ -48,7 +42,7 @@ fun DynamicTopAppBar( title: String, subtitle: String? = null, state: ListUiState, - scrollBehavior: TopAppBarScrollBehavior, + scrollBehavior: GlassTopAppBarScrollBehavior, onBackClick: (() -> Unit)? = null, onSearchToggle: (Boolean) -> Unit, onSearchQueryChange: (String) -> Unit, @@ -59,7 +53,7 @@ fun DynamicTopAppBar( onClearSelection: () -> Unit, topBarActions: @Composable RowScope.() -> Unit = {}, dropDownMenuContent: @Composable (ColumnScope.(dismiss: () -> Unit) -> Unit)? = null, - bottomContent: @Composable (ColumnScope.(TopAppBarScrollBehavior) -> Unit)? = null + bottomContent: @Composable (ColumnScope.(GlassTopAppBarScrollBehavior) -> Unit)? = null ) { var showMenu by remember { mutableStateOf(false) } val isSelecting = state.selectedIds.isNotEmpty() @@ -67,93 +61,84 @@ fun DynamicTopAppBar( val containerColor = GlassTopAppBarDefaults.containerColor() val scrolledColor = GlassTopAppBarDefaults.scrolledContainerColor() - val collapsedFraction = scrollBehavior.state.collapsedFraction + val animatedColor by remember(scrollBehavior, containerColor, scrolledColor) { + derivedStateOf { + lerp(containerColor, scrolledColor, scrollBehavior.collapsedFraction) + } + } - val animatedColor by animateColorAsState( - targetValue = lerp(containerColor, scrolledColor, collapsedFraction), - label = "TopBarContainerColor" - ) - - Column( + GlassMediumFlexibleTopAppBar( modifier = Modifier .fillMaxWidth() - .background(animatedColor) - ) { - GlassMediumFlexibleTopAppBar( - title = { - val titleText = when { - state.isLoading -> "请稍后..." - isSelecting -> "已选择 ${state.selectedIds.size}/${state.items.size}" - else -> title - } - AdaptiveAnimatedText( - text = titleText, - useCharMode = isSelecting || state.isLoading, - maxLines = 1, - overflow = TextOverflow.Ellipsis + .background(animatedColor), + title = when { + state.isLoading -> "请稍后..." + isSelecting -> "已选择 ${state.selectedIds.size}/${state.items.size}" + else -> title + }, + useCharMode = isSelecting || state.isLoading, + subtitle = subtitle?.let { + { AnimatedTextLine(text = it) } + }, + navigationIcon = { + if (isSelecting || onBackClick != null) { + TopbarNavigationButton( + onClick = { if (isSelecting) onClearSelection() else onBackClick?.invoke() }, + imageVector = if (isSelecting) Icons.Default.Close else Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = if (isSelecting) "取消选择" else "返回" + ) + } + }, + actions = { + if (!isSelecting) { + TopBarActionButton( + onClick = { onSearchToggle(!state.isSearch) }, + imageVector = Icons.Default.Search, + contentDescription = "搜索" ) - }, - subtitle = subtitle?.let { - { AnimatedTextLine(text = it) } - }, - navigationIcon = { - if (isSelecting || onBackClick != null) { - TopbarNavigationButton( - onClick = { if (isSelecting) onClearSelection() else onBackClick?.invoke() }, - imageVector = if (isSelecting) Icons.Default.Close else Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = if (isSelecting) "取消选择" else "返回" - ) - } - }, - actions = { - if (!isSelecting) { - TopBarActionButton( - onClick = { onSearchToggle(!state.isSearch) }, - imageVector = Icons.Default.Search, - contentDescription = "搜索" - ) - topBarActions() + topBarActions() - dropDownMenuContent?.let { content -> - Box { - TopBarActionButton( - onClick = { showMenu = true }, - imageVector = Icons.Default.MoreVert, - contentDescription = "更多" - ) - RoundDropdownMenu( - expanded = showMenu, - onDismissRequest = { showMenu = false } - ) { dismiss -> - content(dismiss) - } + dropDownMenuContent?.let { content -> + Box { + TopBarActionButton( + onClick = { showMenu = true }, + imageVector = Icons.Default.MoreVert, + contentDescription = "更多" + ) + RoundDropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { dismiss -> + content(dismiss) } } } - }, - scrollBehavior = scrollBehavior, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = Color.Transparent, - scrolledContainerColor = Color.Transparent - ) - ) + } + }, + scrollBehavior = scrollBehavior, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Transparent + ), + bottomContent = { + AnimatedVisibility( + visible = state.isSearch && !isSelecting, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut() + ) { + SearchBarSection( + query = state.searchKey, + onQueryChange = onSearchQueryChange, + placeholder = searchPlaceholder, + leadingIcon = { Icon(searchLeadingIcon, null) }, + trailingIcon = searchTrailingIcon, + dropdownMenu = searchDropdownMenu + ) + } - AnimatedVisibility( - visible = state.isSearch && !isSelecting, - enter = expandVertically() + fadeIn(), - exit = shrinkVertically() + fadeOut() - ) { - SearchBarSection( - query = state.searchKey, - onQueryChange = onSearchQueryChange, - placeholder = searchPlaceholder, - leadingIcon = { Icon(searchLeadingIcon, null) }, - trailingIcon = searchTrailingIcon, - dropdownMenu = searchDropdownMenu - ) + bottomContent?.invoke(this, scrollBehavior) } - - bottomContent?.invoke(this, scrollBehavior) - } + ) } + diff --git a/app/src/main/java/io/legado/app/ui/widget/components/topbar/GlassMediumFlexibleTopAppBar.kt b/app/src/main/java/io/legado/app/ui/widget/components/topbar/GlassMediumFlexibleTopAppBar.kt new file mode 100644 index 000000000..e06f0d6da --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/topbar/GlassMediumFlexibleTopAppBar.kt @@ -0,0 +1,178 @@ +package io.legado.app.ui.widget.components.topbar + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.MediumFlexibleTopAppBar +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarColors +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextOverflow +import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.theme.LocalHazeState +import io.legado.app.ui.theme.ThemeResolver +import io.legado.app.ui.theme.responsiveHazeEffect +import io.legado.app.ui.widget.components.AdaptiveAnimatedText +import io.legado.app.ui.widget.components.GlassDefaults +import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior +import top.yukonga.miuix.kmp.theme.MiuixTheme +import top.yukonga.miuix.kmp.basic.TopAppBar as MiuixTopAppBar + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun GlassMediumFlexibleTopAppBar( + title: String, + modifier: Modifier = Modifier, + useCharMode: Boolean = false, + subtitle: (@Composable () -> Unit)? = null, + scrollBehavior: GlassTopAppBarScrollBehavior? = null, + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, + colors: TopAppBarColors = GlassTopAppBarDefaults.glassColors(), + bottomContent: @Composable (ColumnScope.() -> Unit)? = null +) { + + val hazeState = LocalHazeState.current + val finalModifier = if (hazeState != null) { + modifier.responsiveHazeEffect(state = hazeState) + } else { + modifier + } + + val composeEngine = LegadoTheme.composeEngine + + Column(modifier = finalModifier) { + when { + ThemeResolver.isMiuixEngine(composeEngine) -> { + MiuixTopAppBar( + modifier = Modifier, + title = title, + navigationIcon = navigationIcon, + actions = actions, + color = GlassTopAppBarDefaults.getMiuixAppBarColor(), + scrollBehavior = (scrollBehavior as? MiuixGlassScrollBehavior)?.miuixBehavior + ) + } + + else -> { + if (ThemeConfig.useFlexibleTopAppBar) { + MediumFlexibleTopAppBar( + modifier = Modifier, + title = { + AdaptiveAnimatedText( + text = title, + useCharMode = useCharMode, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + subtitle = subtitle, + navigationIcon = navigationIcon, + actions = actions, + scrollBehavior = (scrollBehavior as? M3GlassScrollBehavior)?.m3Behavior, + colors = colors + ) + } else { + TopAppBar( + modifier = Modifier, + title = { + AdaptiveAnimatedText( + text = title, + useCharMode = useCharMode, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + navigationIcon = navigationIcon, + actions = actions, + scrollBehavior = (scrollBehavior as? M3GlassScrollBehavior)?.m3Behavior, + colors = colors + ) + } + } + } + bottomContent?.invoke(this) + } +} + +object GlassTopAppBarDefaults { + + @Composable + fun getMiuixAppBarColor() = GlassDefaults.glassColor( + noBlurColor = MiuixTheme.colorScheme.surface, + blurAlpha = GlassDefaults.TransparentAlpha + ) + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun defaultScrollBehavior(): GlassTopAppBarScrollBehavior { + val composeEngine = ThemeConfig.composeEngine + + return if (ThemeResolver.isMiuixEngine(composeEngine)) { + MiuixGlassScrollBehavior(MiuixScrollBehavior()) + } else if (ThemeConfig.useFlexibleTopAppBar) { + M3GlassScrollBehavior(TopAppBarDefaults.exitUntilCollapsedScrollBehavior()) + } else { + M3GlassScrollBehavior(TopAppBarDefaults.pinnedScrollBehavior()) + } + } + + @Composable + fun glassColors(): TopAppBarColors { + + val containerColor = GlassDefaults.glassColor( + noBlurColor = MaterialTheme.colorScheme.surface, + blurAlpha = GlassDefaults.TransparentAlpha + ) + + val scrolledContainerColor = if (ThemeConfig.enableBlur) { + MaterialTheme.colorScheme.surface.copy(alpha = GlassDefaults.TransparentAlpha) + } else { + MaterialTheme.colorScheme.surfaceContainer + } + + return TopAppBarDefaults.topAppBarColors( + containerColor = applyTopBarOpacity(containerColor), + scrolledContainerColor = applyTopBarOpacity(scrolledContainerColor) + ) + } + + @Composable + fun containerColor(): Color { + val baseColor = GlassDefaults.glassColor( + noBlurColor = MaterialTheme.colorScheme.surface, + blurAlpha = GlassDefaults.TransparentAlpha + ) + return applyTopBarOpacity(baseColor) + } + + @Composable + fun scrolledContainerColor(): Color { + val baseColor = GlassDefaults.glassColor( + noBlurColor = MaterialTheme.colorScheme.surfaceContainer, + blurAlpha = GlassDefaults.TransparentAlpha + ) + return applyTopBarOpacity(baseColor) + } + + @Composable + fun controlContainerColor(): Color { + val baseColor = GlassDefaults.glassColor( + noBlurColor = MaterialTheme.colorScheme.surfaceContainerHighest, + blurAlpha = GlassDefaults.DefaultBlurAlpha + ) + return applyTopBarOpacity(baseColor) + } + + private fun applyTopBarOpacity(color: Color): Color { + val opacity = (ThemeConfig.topBarOpacity.coerceIn(0, 100)) / 100f + return color.copy(alpha = (color.alpha * opacity).coerceIn(0f, 1f)) + } +} diff --git a/app/src/main/java/io/legado/app/ui/widget/components/topbar/MiuixScrollBehavior.kt b/app/src/main/java/io/legado/app/ui/widget/components/topbar/MiuixScrollBehavior.kt new file mode 100644 index 000000000..f393d8b8e --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/components/topbar/MiuixScrollBehavior.kt @@ -0,0 +1,36 @@ +package io.legado.app.ui.widget.components.topbar + +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import top.yukonga.miuix.kmp.basic.ScrollBehavior + + +interface GlassTopAppBarScrollBehavior { + // 滚动连接器 + val nestedScrollConnection: NestedScrollConnection + + // 折叠进度:0f 表示完全展开,1f 表示完全折叠。 + val collapsedFraction: Float +} + +@OptIn(ExperimentalMaterial3Api::class) +class M3GlassScrollBehavior( + val m3Behavior: TopAppBarScrollBehavior +) : GlassTopAppBarScrollBehavior { + override val nestedScrollConnection: NestedScrollConnection + get() = m3Behavior.nestedScrollConnection + + override val collapsedFraction: Float + get() = m3Behavior.state.collapsedFraction +} + +class MiuixGlassScrollBehavior( + val miuixBehavior: ScrollBehavior +) : GlassTopAppBarScrollBehavior { + override val nestedScrollConnection: NestedScrollConnection + get() = miuixBehavior.nestedScrollConnection + + override val collapsedFraction: Float + get() = miuixBehavior.state.collapsedFraction +} \ No newline at end of file diff --git a/app/version.properties b/app/version.properties index a5149387f..910d3613b 100644 --- a/app/version.properties +++ b/app/version.properties @@ -1,5 +1,5 @@ VERSION_MAJOR=3 VERSION_MINOR=26 -VERSION_PATCH=9 -VERSION_SUFFIX=0 +VERSION_PATCH=10 +VERSION_SUFFIX=1 # 1 = Pre, 0 = Release \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 275c1ac83..8dadc71c4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,14 +4,14 @@ accompanistWebview = "0.36.0" adaptive = "1.3.0-alpha09" adaptiveLayout = "1.3.0-alpha09" adaptiveNavigation = "1.3.0-alpha09" -animation = "1.10.1" -biometric = "1.2.0" +animation = "1.10.6" +biometric = "1.4.0-alpha06" coilCompose = "2.7.0" -composeBom = "2026.03.00" +composeBom = "2026.03.01" constraintlayoutCompose = "1.1.1" coreSplashscreen = "1.2.0" datastorePreferences = "1.2.1" -foundation = "1.10.5" +foundation = "1.10.6" kotlin = "2.3.10" kotlinxSerialization = "1.10.0" kotlinxCoroutinesAndroid = "1.10.2" @@ -83,6 +83,10 @@ biometricKtx = "1.1.0" reorderable = "3.0.0" haze = "1.7.2" +timber = "5.0.1" +miuix = "0.8.8" +backdrop = "1.0.6" +capsule = "2.1.3" [libraries] accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanistWebview" } @@ -239,6 +243,16 @@ androidx-biometric-ktx = { group = "androidx.biometric", name = "biometric-ktx", reorderable = { module = "sh.calvin.reorderable:reorderable", version.ref = "reorderable" } +# log +timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" } + +# miuix +miuix = { group = "top.yukonga.miuix.kmp", name = "miuix-android", version.ref = "miuix" } +miuix-icons = { group = "top.yukonga.miuix.kmp", name = "miuix-icons-android", version.ref = "miuix" } + +capsule = { module = "io.github.kyant0:capsule", version.ref = "capsule" } +backdrop = { module = "io.github.kyant0:backdrop", version.ref = "backdrop" } + [bundles] coroutines = ["kotlinx-coroutines-core", "kotlinx-coroutines-android"] androidTest = ["androidx-espresso-core", "androidx-junit", "androidx-runner"]