初始版本
This commit is contained in:
@@ -286,4 +286,9 @@ dependencies {
|
|||||||
implementation(libs.material.kolor)
|
implementation(libs.material.kolor)
|
||||||
implementation(libs.haze.core)
|
implementation(libs.haze.core)
|
||||||
implementation(libs.haze.materials)
|
implementation(libs.haze.materials)
|
||||||
|
implementation(libs.miuix)
|
||||||
|
implementation(libs.miuix.icons)
|
||||||
|
implementation(libs.capsule)
|
||||||
|
implementation(libs.backdrop)
|
||||||
|
implementation(libs.timber)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -113,6 +114,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -141,6 +143,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -169,6 +172,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -202,6 +206,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -236,6 +241,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -265,6 +271,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -293,6 +300,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -321,6 +329,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -350,6 +359,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -378,6 +388,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -406,6 +417,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -434,6 +446,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
@@ -462,6 +475,7 @@ interface BookDao {
|
|||||||
durChapterPos,
|
durChapterPos,
|
||||||
latestChapterTitle,
|
latestChapterTitle,
|
||||||
latestChapterTime,
|
latestChapterTime,
|
||||||
|
lastCheckCount,
|
||||||
totalChapterNum,
|
totalChapterNum,
|
||||||
durChapterIndex,
|
durChapterIndex,
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.FilledTonalIconButton
|
import androidx.compose.material3.FilledTonalIconButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -31,13 +29,15 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.AppConst.appInfo
|
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.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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.card.TextCard
|
||||||
import io.legado.app.ui.widget.components.settingItem.SettingItem
|
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)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -59,7 +59,7 @@ fun AboutScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(stringResource(R.string.about)) },
|
title = stringResource(R.string.about),
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
@@ -81,9 +81,9 @@ fun AboutScreen(
|
|||||||
.width(160.dp)
|
.width(160.dp)
|
||||||
.align(Alignment.CenterHorizontally)
|
.align(Alignment.CenterHorizontally)
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.app_name),
|
text = stringResource(R.string.app_name),
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = LegadoTheme.typography.bodyLarge,
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -98,9 +98,9 @@ fun AboutScreen(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentWidth(Alignment.CenterHorizontally)
|
.wrapContentWidth(Alignment.CenterHorizontally)
|
||||||
.padding(vertical = 4.dp))
|
.padding(vertical = 4.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.about_description),
|
text = stringResource(R.string.about_description),
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = LegadoTheme.typography.bodyLarge,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -31,7 +30,9 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.AppLog
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.LogUtils
|
import io.legado.app.utils.LogUtils
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@@ -52,9 +53,9 @@ fun AppLogSheet(
|
|||||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.log),
|
text = stringResource(R.string.log),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
@@ -82,17 +83,17 @@ fun AppLogSheet(
|
|||||||
showStackTrace?.let { stackTrace ->
|
showStackTrace?.let { stackTrace ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showStackTrace = null },
|
onDismissRequest = { showStackTrace = null },
|
||||||
title = { Text("Log") },
|
title = { AppText("Log") },
|
||||||
text = {
|
text = {
|
||||||
SelectionContainer {
|
SelectionContainer {
|
||||||
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
||||||
Text(text = stackTrace, style = MaterialTheme.typography.bodySmall)
|
AppText(text = stackTrace, style = LegadoTheme.typography.bodySmall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = { showStackTrace = null }) {
|
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)
|
.clickable(onClick = onClick)
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = LogUtils.logTimeFormat.format(Date(item.first)),
|
text = LogUtils.logTimeFormat.format(Date(item.first)),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
color = MaterialTheme.colorScheme.outline
|
color = MaterialTheme.colorScheme.outline
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = item.second,
|
text = item.second,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
modifier = Modifier.padding(top = 4.dp)
|
modifier = Modifier.padding(top = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
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.CollapsibleHeader
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
import io.legado.app.ui.widget.components.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
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.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkItem
|
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.lazylist.Scroller
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.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
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
|
||||||
@@ -98,11 +98,7 @@ fun AllBookmarkScreen(
|
|||||||
topBar = {
|
topBar = {
|
||||||
Column {
|
Column {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = "所有书签",
|
||||||
Text(
|
|
||||||
text = "所有书签"
|
|
||||||
)
|
|
||||||
},
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
@@ -132,7 +128,7 @@ fun AllBookmarkScreen(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 JSON") },
|
text = { AppText("导出 JSON") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
pendingExportIsMd = false
|
pendingExportIsMd = false
|
||||||
@@ -140,7 +136,7 @@ fun AllBookmarkScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 Markdown") },
|
text = { AppText("导出 Markdown") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
pendingExportIsMd = true
|
pendingExportIsMd = true
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
|
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
|
||||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
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.SearchBook
|
||||||
import io.legado.app.data.entities.rule.ExploreKind
|
import io.legado.app.data.entities.rule.ExploreKind
|
||||||
import io.legado.app.model.BookShelfState
|
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.responsiveHazeEffect
|
||||||
import io.legado.app.ui.theme.responsiveHazeSource
|
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.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.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.button.AnimatedTextButton
|
import io.legado.app.ui.widget.components.button.AnimatedTextButton
|
||||||
import io.legado.app.ui.widget.components.button.TopBarActionButton
|
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.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.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.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -194,16 +194,16 @@ fun ExploreShowScreen(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = "布局列数",
|
text = "布局列数",
|
||||||
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)
|
style = LegadoTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
|
||||||
TextCard(
|
TextCard(
|
||||||
text = "$gridColumnCount 列",
|
text = "$gridColumnCount 列",
|
||||||
textStyle = MaterialTheme.typography.titleSmall,
|
textStyle = LegadoTheme.typography.titleSmall,
|
||||||
verticalPadding = 4.dp,
|
verticalPadding = 4.dp,
|
||||||
horizontalPadding = 12.dp,
|
horizontalPadding = 12.dp,
|
||||||
cornerRadius = 12.dp
|
cornerRadius = 12.dp
|
||||||
@@ -229,7 +229,7 @@ fun ExploreShowScreen(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Text("完成")
|
AppText("完成")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,13 +294,7 @@ fun ExploreShowScreen(
|
|||||||
modifier = Modifier.responsiveHazeEffect(
|
modifier = Modifier.responsiveHazeEffect(
|
||||||
state = hazeState
|
state = hazeState
|
||||||
),
|
),
|
||||||
title = {
|
title = selectedTitle ?: title,
|
||||||
AnimatedTextLine(
|
|
||||||
selectedTitle ?: title,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
},
|
|
||||||
colors = GlassTopAppBarDefaults.glassColors(),
|
colors = GlassTopAppBarDefaults.glassColors(),
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
@@ -346,7 +340,7 @@ fun ExploreShowScreen(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("全部显示") },
|
text = { AppText("全部显示") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.SHOW_ALL)
|
viewModel.setFilterState(BookFilterState.SHOW_ALL)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -358,7 +352,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("隐藏已在书架的同源书籍") },
|
text = { AppText("隐藏已在书架的同源书籍") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.HIDE_IN_SHELF)
|
viewModel.setFilterState(BookFilterState.HIDE_IN_SHELF)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -370,7 +364,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("隐藏已在书架的非同源书籍") },
|
text = { AppText("隐藏已在书架的非同源书籍") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.HIDE_SAME_NAME_AUTHOR)
|
viewModel.setFilterState(BookFilterState.HIDE_SAME_NAME_AUTHOR)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -382,7 +376,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("只显示不在书架的书籍") },
|
text = { AppText("只显示不在书架的书籍") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.SHOW_NOT_IN_SHELF_ONLY)
|
viewModel.setFilterState(BookFilterState.SHOW_NOT_IN_SHELF_ONLY)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -509,7 +503,7 @@ fun KindGridItem(
|
|||||||
enabled = isClickable,
|
enabled = isClickable,
|
||||||
selected = isSelected,
|
selected = isSelected,
|
||||||
label = {
|
label = {
|
||||||
Text(
|
AppText(
|
||||||
text = kind.title,
|
text = kind.title,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -576,32 +570,32 @@ fun ExploreBookItem(
|
|||||||
.weight(1f)
|
.weight(1f)
|
||||||
.align(Alignment.CenterVertically)) {
|
.align(Alignment.CenterVertically)) {
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = book.name,
|
text = book.name,
|
||||||
style = MaterialTheme.typography.titleSmall,
|
style = LegadoTheme.typography.titleSmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
Text(
|
AppText(
|
||||||
text = book.author,
|
text = book.author,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
val latestChapter = book.latestChapterTitle
|
val latestChapter = book.latestChapterTitle
|
||||||
if (!latestChapter.isNullOrEmpty()) {
|
if (!latestChapter.isNullOrEmpty()) {
|
||||||
Text(
|
AppText(
|
||||||
text = " • ",
|
text = " • ",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = Color.Gray,
|
color = Color.Gray,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = "最新: $latestChapter",
|
text = "最新: $latestChapter",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
@@ -612,9 +606,9 @@ fun ExploreBookItem(
|
|||||||
|
|
||||||
val intro = book.intro?.replace("\\s+".toRegex(), "") ?: ""
|
val intro = book.intro?.replace("\\s+".toRegex(), "") ?: ""
|
||||||
if (intro.isNotEmpty()) {
|
if (intro.isNotEmpty()) {
|
||||||
Text(
|
AppText(
|
||||||
text = intro,
|
text = intro,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
color = Color.Gray,
|
color = Color.Gray,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
minLines = 2,
|
minLines = 2,
|
||||||
@@ -654,9 +648,12 @@ fun ExploreBookGridItem(
|
|||||||
|
|
||||||
val content: (@Composable RowScope.() -> Unit)? = if (!badgeText.isNullOrBlank()) {
|
val content: (@Composable RowScope.() -> Unit)? = if (!badgeText.isNullOrBlank()) {
|
||||||
{
|
{
|
||||||
Text(
|
AppText(
|
||||||
text = badgeText,
|
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 {
|
} else {
|
||||||
@@ -681,9 +678,9 @@ fun ExploreBookGridItem(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = book.name,
|
text = book.name,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -698,10 +695,10 @@ fun TagChip(text: String) {
|
|||||||
color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f),
|
color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f),
|
||||||
shape = RoundedCornerShape(4.dp)
|
shape = RoundedCornerShape(4.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = text,
|
text = text,
|
||||||
modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp),
|
modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp),
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -742,13 +739,13 @@ fun LoadMoreFooter(
|
|||||||
},
|
},
|
||||||
label = "FooterTextChange"
|
label = "FooterTextChange"
|
||||||
) { text ->
|
) { text ->
|
||||||
Text(
|
AppText(
|
||||||
text = text,
|
text = text,
|
||||||
color = when {
|
color = when {
|
||||||
errorMsg != null -> Color.Red
|
errorMsg != null -> Color.Red
|
||||||
else -> Color.Gray
|
else -> Color.Gray
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.bodySmall
|
style = LegadoTheme.typography.bodySmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,9 @@ import androidx.compose.material.icons.filled.Restore
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedIconButton
|
import androidx.compose.material3.OutlinedIconButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
@@ -38,10 +36,12 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.lib.dialogs.alert
|
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.cover.Cover
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
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.CompactDropdownSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem
|
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.FileUtils
|
||||||
import io.legado.app.utils.MD5Utils
|
import io.legado.app.utils.MD5Utils
|
||||||
import io.legado.app.utils.SelectImageContract
|
import io.legado.app.utils.SelectImageContract
|
||||||
@@ -113,9 +113,9 @@ fun GroupEditContent(
|
|||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState()),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.group_edit),
|
text = stringResource(R.string.group_edit),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(vertical = 16.dp)
|
modifier = Modifier.padding(vertical = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ fun GroupEditContent(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = groupName,
|
value = groupName,
|
||||||
onValueChange = { groupName = it },
|
onValueChange = { groupName = it },
|
||||||
label = { Text(stringResource(R.string.group_name)) },
|
label = { AppText(stringResource(R.string.group_name)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
@@ -206,7 +206,7 @@ fun GroupEditContent(
|
|||||||
|
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
OutlinedButton(onClick = onDismissRequest) {
|
OutlinedButton(onClick = onDismissRequest) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
if (groupName.isEmpty()) {
|
if (groupName.isEmpty()) {
|
||||||
@@ -235,7 +235,7 @@ fun GroupEditContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.RadioButton
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
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.data.entities.Server
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.model.remote.RemoteBook
|
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.ActionItem
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
import io.legado.app.ui.widget.components.EmptyMessageView
|
||||||
import io.legado.app.ui.widget.components.SelectionActions
|
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.list.ListScaffold
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.ArchiveUtils
|
import io.legado.app.utils.ArchiveUtils
|
||||||
import io.legado.app.utils.ConvertUtils
|
import io.legado.app.utils.ConvertUtils
|
||||||
import io.legado.app.utils.FileDoc
|
import io.legado.app.utils.FileDoc
|
||||||
@@ -157,19 +158,19 @@ fun RemoteBookScreen(
|
|||||||
is RemoteBookDialog.DownloadArchive -> {
|
is RemoteBookDialog.DownloadArchive -> {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { dialogState = null },
|
onDismissRequest = { dialogState = null },
|
||||||
title = { Text(stringResource(R.string.draw)) },
|
title = { AppText(stringResource(R.string.draw)) },
|
||||||
text = { Text(stringResource(R.string.archive_not_found)) },
|
text = { AppText(stringResource(R.string.archive_not_found)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) }
|
scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) }
|
||||||
dialogState = null
|
dialogState = null
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(android.R.string.ok))
|
AppText(stringResource(android.R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { dialogState = null }) {
|
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 -> {
|
is RemoteBookDialog.ReImport -> {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { dialogState = null },
|
onDismissRequest = { dialogState = null },
|
||||||
title = { Text("是否重新加入书架?") },
|
title = { AppText("是否重新加入书架?") },
|
||||||
text = { Text("将会覆盖书籍") },
|
text = { AppText("将会覆盖书籍") },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) }
|
scope.launch { viewModel.addToBookshelf(setOf(state.remoteBook)) }
|
||||||
dialogState = null
|
dialogState = null
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(android.R.string.ok))
|
AppText(stringResource(android.R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { dialogState = null }) {
|
TextButton(onClick = { dialogState = null }) {
|
||||||
Text(stringResource(android.R.string.cancel))
|
AppText(stringResource(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -259,7 +260,7 @@ fun RemoteBookScreen(
|
|||||||
},
|
},
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("按名称排序") },
|
text = { AppText("按名称排序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.toggleSort(RemoteBookSort.Name)
|
viewModel.toggleSort(RemoteBookSort.Name)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -271,7 +272,7 @@ fun RemoteBookScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("按时间排序") },
|
text = { AppText("按时间排序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.toggleSort(RemoteBookSort.Default)
|
viewModel.toggleSort(RemoteBookSort.Default)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -381,9 +382,9 @@ private fun ServersSheetContent(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.server_config),
|
text = stringResource(R.string.server_config),
|
||||||
style = MaterialTheme.typography.titleLarge
|
style = LegadoTheme.typography.titleLarge
|
||||||
)
|
)
|
||||||
IconButton(onClick = onAdd) {
|
IconButton(onClick = onAdd) {
|
||||||
Icon(Icons.Default.Add, contentDescription = "添加")
|
Icon(Icons.Default.Add, contentDescription = "添加")
|
||||||
@@ -447,9 +448,9 @@ private fun ServerItem(
|
|||||||
ListItem(
|
ListItem(
|
||||||
modifier = Modifier.animateContentSize(),
|
modifier = Modifier.animateContentSize(),
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
AppText(
|
||||||
text = name,
|
text = name,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
@@ -462,9 +463,9 @@ private fun ServerItem(
|
|||||||
},
|
},
|
||||||
supportingContent = url?.let {
|
supportingContent = url?.let {
|
||||||
{
|
{
|
||||||
Text(
|
AppText(
|
||||||
text = it,
|
text = it,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -514,16 +515,16 @@ private fun ServerConfigSheetContent(
|
|||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = if (server == null) "添加服务器" else "编辑服务器",
|
text = if (server == null) "添加服务器" else "编辑服务器",
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = name,
|
value = name,
|
||||||
onValueChange = { name = it },
|
onValueChange = { name = it },
|
||||||
label = { Text("名称") },
|
label = { AppText("名称") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
@@ -531,7 +532,7 @@ private fun ServerConfigSheetContent(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = url,
|
value = url,
|
||||||
onValueChange = { url = it },
|
onValueChange = { url = it },
|
||||||
label = { Text("URL") },
|
label = { AppText("URL") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
@@ -539,7 +540,7 @@ private fun ServerConfigSheetContent(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = username,
|
value = username,
|
||||||
onValueChange = { username = it },
|
onValueChange = { username = it },
|
||||||
label = { Text("用户名") },
|
label = { AppText("用户名") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
@@ -547,7 +548,7 @@ private fun ServerConfigSheetContent(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = password,
|
value = password,
|
||||||
onValueChange = { password = it },
|
onValueChange = { password = it },
|
||||||
label = { Text("密码") },
|
label = { AppText("密码") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||||
@@ -571,7 +572,7 @@ private fun ServerConfigSheetContent(
|
|||||||
onClick = onCancel,
|
onClick = onCancel,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(android.R.string.cancel))
|
AppText(stringResource(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -587,7 +588,7 @@ private fun ServerConfigSheetContent(
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
enabled = name.isNotBlank() && url.isNotBlank()
|
enabled = name.isNotBlank() && url.isNotBlank()
|
||||||
) {
|
) {
|
||||||
Text("保存")
|
AppText("保存")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -625,9 +626,9 @@ private fun PathNavigationBar(
|
|||||||
itemsIndexed(pathNames) { index, name ->
|
itemsIndexed(pathNames) { index, name ->
|
||||||
val isLast = index == pathNames.lastIndex
|
val isLast = index == pathNames.lastIndex
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = name,
|
text = name,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
fontWeight = if (isLast) FontWeight.SemiBold else FontWeight.Medium,
|
fontWeight = if (isLast) FontWeight.SemiBold else FontWeight.Medium,
|
||||||
color = if (isLast)
|
color = if (isLast)
|
||||||
MaterialTheme.colorScheme.primary
|
MaterialTheme.colorScheme.primary
|
||||||
@@ -716,9 +717,9 @@ private fun RemoteBookItem(
|
|||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = book.filename.substringBeforeLast("."),
|
text = book.filename.substringBeforeLast("."),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
@@ -732,7 +733,7 @@ private fun RemoteBookItem(
|
|||||||
if (book.contentType.isNotEmpty()) {
|
if (book.contentType.isNotEmpty()) {
|
||||||
TextCard(
|
TextCard(
|
||||||
text = book.contentType.uppercase(),
|
text = book.contentType.uppercase(),
|
||||||
textStyle = MaterialTheme.typography.labelSmall,
|
textStyle = LegadoTheme.typography.labelSmall,
|
||||||
horizontalPadding = 4.dp,
|
horizontalPadding = 4.dp,
|
||||||
verticalPadding = 2.dp,
|
verticalPadding = 2.dp,
|
||||||
cornerRadius = 4.dp,
|
cornerRadius = 4.dp,
|
||||||
@@ -743,11 +744,11 @@ private fun RemoteBookItem(
|
|||||||
Spacer(modifier = Modifier.width(6.dp))
|
Spacer(modifier = Modifier.width(6.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = "${ConvertUtils.formatFileSize(book.size)} • ${
|
text = "${ConvertUtils.formatFileSize(book.size)} • ${
|
||||||
AppConst.dateFormat.format(book.lastModify)
|
AppConst.dateFormat.format(book.lastModify)
|
||||||
}",
|
}",
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -47,12 +46,13 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.TopBarButtonVariant
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.cover.Cover
|
||||||
import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
|
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.SelectImageContract
|
||||||
import io.legado.app.utils.launch
|
import io.legado.app.utils.launch
|
||||||
import io.legado.app.utils.showDialogFragment
|
import io.legado.app.utils.showDialogFragment
|
||||||
@@ -71,7 +71,7 @@ fun BookInfoEditScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.book_info_edit)) },
|
title = stringResource(id = R.string.book_info_edit),
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(
|
TopbarNavigationButton(
|
||||||
onClick = onBack,
|
onClick = onBack,
|
||||||
@@ -191,35 +191,35 @@ fun BookInfoEditContent(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = uiState.name,
|
value = uiState.name,
|
||||||
onValueChange = { viewModel.onNameChange(it) },
|
onValueChange = { viewModel.onNameChange(it) },
|
||||||
label = { Text("书名") },
|
label = { AppText("书名") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = uiState.author,
|
value = uiState.author,
|
||||||
onValueChange = { viewModel.onAuthorChange(it) },
|
onValueChange = { viewModel.onAuthorChange(it) },
|
||||||
label = { Text("作者") },
|
label = { AppText("作者") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = uiState.coverUrl ?: "",
|
value = uiState.coverUrl ?: "",
|
||||||
onValueChange = { viewModel.onCoverUrlChange(it) },
|
onValueChange = { viewModel.onCoverUrlChange(it) },
|
||||||
label = { Text("封面链接") },
|
label = { AppText("封面链接") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = uiState.intro ?: "",
|
value = uiState.intro ?: "",
|
||||||
onValueChange = { viewModel.onIntroChange(it) },
|
onValueChange = { viewModel.onIntroChange(it) },
|
||||||
label = { Text("简介") },
|
label = { AppText("简介") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = uiState.remark ?: "",
|
value = uiState.remark ?: "",
|
||||||
onValueChange = { viewModel.onRemarkChange(it) },
|
onValueChange = { viewModel.onRemarkChange(it) },
|
||||||
label = { Text("备注") },
|
label = { AppText("备注") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ fun BookTypeDropdown(
|
|||||||
state = textFieldState,
|
state = textFieldState,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
lineLimits = TextFieldLineLimits.SingleLine,
|
lineLimits = TextFieldLineLimits.SingleLine,
|
||||||
label = { Text("书籍类型") },
|
label = { AppText("书籍类型") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
|
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
|
||||||
},
|
},
|
||||||
@@ -269,7 +269,7 @@ fun BookTypeDropdown(
|
|||||||
) {
|
) {
|
||||||
bookTypes.forEach { option ->
|
bookTypes.forEach { option ->
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(option) },
|
text = { AppText(option) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onTypeSelected(option)
|
onTypeSelected(option)
|
||||||
expanded = false
|
expanded = false
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -78,11 +77,10 @@ import androidx.compose.ui.zIndex
|
|||||||
import cn.hutool.core.date.DateUtil
|
import cn.hutool.core.date.DateUtil
|
||||||
import io.legado.app.data.entities.readRecord.ReadRecord
|
import io.legado.app.data.entities.readRecord.ReadRecord
|
||||||
import io.legado.app.data.entities.readRecord.ReadRecordDetail
|
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.AnimatedTextLine
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
import io.legado.app.ui.widget.components.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
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.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.SectionHeader
|
import io.legado.app.ui.widget.components.SectionHeader
|
||||||
import io.legado.app.ui.widget.components.button.AlertButton
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
import io.legado.app.ui.widget.components.swipe.SwipeAction
|
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.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 io.legado.app.utils.StringUtils.formatFriendlyDate
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -148,11 +149,7 @@ fun ReadRecordScreen(
|
|||||||
topBar = {
|
topBar = {
|
||||||
Column {
|
Column {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = "阅读记录",
|
||||||
Text(
|
|
||||||
text = "阅读记录"
|
|
||||||
)
|
|
||||||
},
|
|
||||||
subtitle = {
|
subtitle = {
|
||||||
val subTitle = when (displayMode) {
|
val subTitle = when (displayMode) {
|
||||||
DisplayMode.AGGREGATE -> "汇总视图"
|
DisplayMode.AGGREGATE -> "汇总视图"
|
||||||
@@ -271,10 +268,10 @@ fun ReadRecordScreen(
|
|||||||
onDismissRequest = {
|
onDismissRequest = {
|
||||||
pendingDeleteAction = null
|
pendingDeleteAction = null
|
||||||
},
|
},
|
||||||
title = { Text("确认删除") },
|
title = { AppText("确认删除") },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
Text("确定要删除这条记录吗?")
|
AppText("确定要删除这条记录吗?")
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -289,10 +286,10 @@ fun ReadRecordScreen(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Checkbox(checked = skipDeleteConfirmTemp, onCheckedChange = null)
|
Checkbox(checked = skipDeleteConfirmTemp, onCheckedChange = null)
|
||||||
Text(
|
AppText(
|
||||||
text = "不再提示",
|
text = "不再提示",
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = LegadoTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +308,7 @@ fun ReadRecordScreen(
|
|||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
pendingDeleteAction = null
|
pendingDeleteAction = null
|
||||||
}) {
|
}) {
|
||||||
Text("取消")
|
AppText("取消")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -346,10 +343,10 @@ fun ReadRecordScreen(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { mergeDialogData = null },
|
onDismissRequest = { mergeDialogData = null },
|
||||||
title = { Text("合并阅读记录") },
|
title = { AppText("合并阅读记录") },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
Text("将以下作者的“${targetRecord.bookName}”合并到 ${targetRecord.bookAuthor.ifBlank { "未知作者" }}")
|
AppText("将以下作者的“${targetRecord.bookName}”合并到 ${targetRecord.bookAuthor.ifBlank { "未知作者" }}")
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
candidates.forEach { candidate ->
|
candidates.forEach { candidate ->
|
||||||
@@ -367,10 +364,10 @@ fun ReadRecordScreen(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Checkbox(checked = isChecked, onCheckedChange = null)
|
Checkbox(checked = isChecked, onCheckedChange = null)
|
||||||
Text(
|
AppText(
|
||||||
text = "$author(${formatDuring(candidate.readTime)})",
|
text = "$author(${formatDuring(candidate.readTime)})",
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = LegadoTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,12 +383,12 @@ fun ReadRecordScreen(
|
|||||||
mergeDialogData = null
|
mergeDialogData = null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text("合并")
|
AppText("合并")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { mergeDialogData = null }) {
|
TextButton(onClick = { mergeDialogData = null }) {
|
||||||
Text("取消")
|
AppText("取消")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -686,21 +683,21 @@ fun LatestReadItem(
|
|||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
Text(
|
AppText(
|
||||||
text = record.bookName,
|
text = record.bookName,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = record.bookAuthor.ifBlank { "未知作者" },
|
text = record.bookAuthor.ifBlank { "未知作者" },
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.outline,
|
color = MaterialTheme.colorScheme.outline,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.basicMarquee(
|
.basicMarquee(
|
||||||
iterations = Int.MAX_VALUE,
|
iterations = Int.MAX_VALUE,
|
||||||
@@ -716,7 +713,7 @@ fun LatestReadItem(
|
|||||||
append("${DateUtil.format(Date(record.lastRead), "yyyy-MM-dd HH:mm")}")
|
append("${DateUtil.format(Date(record.lastRead), "yyyy-MM-dd HH:mm")}")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
@@ -783,9 +780,9 @@ fun TimelineSessionItem(
|
|||||||
modifier = Modifier.width(48.dp),
|
modifier = Modifier.width(48.dp),
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = endTimeText,
|
text = endTimeText,
|
||||||
style = MaterialTheme.typography.bodySmall
|
style = LegadoTheme.typography.bodySmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,23 +792,23 @@ fun TimelineSessionItem(
|
|||||||
Cover(coverPath)
|
Cover(coverPath)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
Column {
|
Column {
|
||||||
Text(
|
AppText(
|
||||||
text = session.bookName,
|
text = session.bookName,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = session.bookAuthor.ifBlank { "未知作者" },
|
text = session.bookAuthor.ifBlank { "未知作者" },
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.outline,
|
color = MaterialTheme.colorScheme.outline,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = chapterTitle.orEmpty(),
|
text = chapterTitle.orEmpty(),
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
color = MaterialTheme.colorScheme.outline,
|
color = MaterialTheme.colorScheme.outline,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -847,21 +844,21 @@ fun ReadRecordItem(
|
|||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
Text(
|
AppText(
|
||||||
text = detail.bookName,
|
text = detail.bookName,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = detail.bookAuthor.ifBlank { "未知作者" },
|
text = detail.bookAuthor.ifBlank { "未知作者" },
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.outline,
|
color = MaterialTheme.colorScheme.outline,
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = "阅读时长: ${formatDuring(detail.readTime)}",
|
text = "阅读时长: ${formatDuring(detail.readTime)}",
|
||||||
color = MaterialTheme.colorScheme.outline,
|
color = MaterialTheme.colorScheme.outline,
|
||||||
style = MaterialTheme.typography.labelSmall
|
style = LegadoTheme.typography.labelSmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -876,17 +873,17 @@ fun DateHeader(
|
|||||||
SectionHeader(
|
SectionHeader(
|
||||||
titleContent = {
|
titleContent = {
|
||||||
Column {
|
Column {
|
||||||
Text(
|
AppText(
|
||||||
text = dateText,
|
text = dateText,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = MaterialTheme.colorScheme.secondary
|
color = MaterialTheme.colorScheme.secondary
|
||||||
)
|
)
|
||||||
|
|
||||||
dailyTotalTime?.let { total ->
|
dailyTotalTime?.let { total ->
|
||||||
Text(
|
AppText(
|
||||||
text = "已读 ${formatDuring(total)}",
|
text = "已读 ${formatDuring(total)}",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -934,28 +931,28 @@ fun ReadingSummaryCard(
|
|||||||
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = LegadoTheme.typography.labelLarge,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
Row(verticalAlignment = Alignment.Bottom) {
|
Row(verticalAlignment = Alignment.Bottom) {
|
||||||
Text(
|
AppText(
|
||||||
text = "已读 ",
|
text = "已读 ",
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = LegadoTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = "$bookCount",
|
text = "$bookCount",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = LegadoTheme.typography.headlineMedium,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = " 本书",
|
text = " 本书",
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = LegadoTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,9 +962,9 @@ fun ReadingSummaryCard(
|
|||||||
val minutes = totalDurationMinutes % 60
|
val minutes = totalDurationMinutes % 60
|
||||||
val timeString = if (hours > 0) "${hours}小时${minutes}分钟" else "${minutes}分钟"
|
val timeString = if (hours > 0) "${hours}小时${minutes}分钟" else "${minutes}分钟"
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = "共阅读 $timeString",
|
text = "共阅读 $timeString",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import androidx.compose.material3.ListItem
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TooltipAnchorPosition
|
import androidx.compose.material3.TooltipAnchorPosition
|
||||||
import androidx.compose.material3.TooltipBox
|
import androidx.compose.material3.TooltipBox
|
||||||
import androidx.compose.material3.TooltipDefaults
|
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.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.data.entities.SearchContentHistory
|
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.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
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.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.button.SmallAnimatedActionButton
|
import io.legado.app.ui.widget.components.button.SmallAnimatedActionButton
|
||||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
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.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
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.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 kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@@ -140,12 +140,9 @@ fun SearchContentScreen(
|
|||||||
topBar = {
|
topBar = {
|
||||||
Column {
|
Column {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = if (searchQuery.isNotBlank() && searchResults.isNotEmpty()) {
|
||||||
val title = if (searchQuery.isNotBlank() && searchResults.isNotEmpty()) {
|
"共 ${searchResults.size} 条结果"
|
||||||
"共 ${searchResults.size} 条结果"
|
} else "搜索内容",
|
||||||
} else "搜索内容"
|
|
||||||
AnimatedText(text = title)
|
|
||||||
},
|
|
||||||
navigationIcon = { TopbarNavigationButton(onClick = onBack) },
|
navigationIcon = { TopbarNavigationButton(onClick = onBack) },
|
||||||
actions = {
|
actions = {
|
||||||
Row(
|
Row(
|
||||||
@@ -191,7 +188,7 @@ fun SearchContentScreen(
|
|||||||
),
|
),
|
||||||
tooltip = {
|
tooltip = {
|
||||||
PlainTooltip {
|
PlainTooltip {
|
||||||
Text(if (isSearching) "停止搜索" else "跳转到当前章节")
|
AppText(if (isSearching) "停止搜索" else "跳转到当前章节")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
state = rememberTooltipState(),
|
state = rememberTooltipState(),
|
||||||
@@ -310,9 +307,9 @@ fun SearchHistoryList(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = "搜索历史",
|
text = "搜索历史",
|
||||||
style = MaterialTheme.typography.titleSmallEmphasized,
|
style = LegadoTheme.typography.titleSmallEmphasized,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier.align(Alignment.Center)
|
modifier = Modifier.align(Alignment.Center)
|
||||||
)
|
)
|
||||||
@@ -342,7 +339,7 @@ fun SearchHistoryList(
|
|||||||
.clickable { onHistoryClick(item) }
|
.clickable { onHistoryClick(item) }
|
||||||
.animateItem(),
|
.animateItem(),
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
AppText(
|
||||||
text = item.query,
|
text = item.query,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -378,7 +375,7 @@ fun SearchHistoryList(
|
|||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Spacer(Modifier.width(8.dp))
|
Spacer(Modifier.width(8.dp))
|
||||||
Text("清除搜索历史")
|
AppText("清除搜索历史")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,7 +404,7 @@ fun SearchResultItem(
|
|||||||
Box(modifier = Modifier.padding(16.dp)) {
|
Box(modifier = Modifier.padding(16.dp)) {
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Text(
|
AppText(
|
||||||
text = buildAnnotatedString {
|
text = buildAnnotatedString {
|
||||||
append(
|
append(
|
||||||
result.getTitleSpannable(
|
result.getTitleSpannable(
|
||||||
@@ -415,14 +412,14 @@ fun SearchResultItem(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.titleSmall
|
style = LegadoTheme.typography.titleSmall
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = buildAnnotatedString {
|
text = buildAnnotatedString {
|
||||||
append(
|
append(
|
||||||
result.getContentSpannable(
|
result.getContentSpannable(
|
||||||
@@ -432,7 +429,7 @@ fun SearchResultItem(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = LegadoTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.PrimaryScrollableTabRow
|
import androidx.compose.material3.PrimaryScrollableTabRow
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.ToggleFloatingActionButton
|
import androidx.compose.material3.ToggleFloatingActionButton
|
||||||
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
|
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
|
||||||
import androidx.compose.material3.animateFloatingActionButton
|
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.help.book.isLocal
|
||||||
import io.legado.app.ui.book.toc.rule.TxtTocRuleActivity
|
import io.legado.app.ui.book.toc.rule.TxtTocRuleActivity
|
||||||
import io.legado.app.ui.replace.ReplaceEditRoute
|
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.CollapsibleHeader
|
||||||
import io.legado.app.ui.widget.components.ActionItem
|
import io.legado.app.ui.widget.components.ActionItem
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
import io.legado.app.ui.widget.components.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
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.SelectionBottomBar
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkItem
|
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.lazylist.FastScrollLazyColumn
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.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.DynamicTopAppBar
|
||||||
|
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -312,33 +313,33 @@ fun TocScreen(
|
|||||||
when (pagerState.currentPage) {
|
when (pagerState.currentPage) {
|
||||||
0 -> {
|
0 -> {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("使用替换规则") },
|
text = { AppText("使用替换规则") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = useReplace, onCheckedChange = null)
|
Checkbox(checked = useReplace, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleUseReplace() }
|
onClick = { viewModel.toggleUseReplace() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("显示字数") },
|
text = { AppText("显示字数") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = showWordCount, onCheckedChange = null)
|
Checkbox(checked = showWordCount, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleShowWordCount() }
|
onClick = { viewModel.toggleShowWordCount() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("反转目录") },
|
text = { AppText("反转目录") },
|
||||||
onClick = { viewModel.reverseToc() }
|
onClick = { viewModel.reverseToc() }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("替换规则") },
|
text = { AppText("替换规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenReplaceRule(null)
|
onOpenReplaceRule(null)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("新建替换规则") },
|
text = { AppText("新建替换规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val scopes = mutableListOf<String>()
|
val scopes = mutableListOf<String>()
|
||||||
book?.name?.let { scopes.add(it) }
|
book?.name?.let { scopes.add(it) }
|
||||||
@@ -358,7 +359,7 @@ fun TocScreen(
|
|||||||
if (book?.isLocal == true) {
|
if (book?.isLocal == true) {
|
||||||
PillHeaderDivider(title = "本地书籍选项")
|
PillHeaderDivider(title = "本地书籍选项")
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("本地书籍目录规则") },
|
text = { AppText("本地书籍目录规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val intent =
|
val intent =
|
||||||
Intent(context, TxtTocRuleActivity::class.java).apply {
|
Intent(context, TxtTocRuleActivity::class.java).apply {
|
||||||
@@ -369,7 +370,7 @@ fun TocScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("拆分超长章节") },
|
text = { AppText("拆分超长章节") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(
|
Checkbox(
|
||||||
checked = viewModel.isSplitLongChapter,
|
checked = viewModel.isSplitLongChapter,
|
||||||
@@ -386,7 +387,7 @@ fun TocScreen(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出书签为JSON") },
|
text = { AppText("导出书签为JSON") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val dateFormat = SimpleDateFormat(
|
val dateFormat = SimpleDateFormat(
|
||||||
"yyyyMMdd_HHmm",
|
"yyyyMMdd_HHmm",
|
||||||
@@ -398,7 +399,7 @@ fun TocScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出书签为MarkDown") },
|
text = { AppText("导出书签为MarkDown") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val dateFormat = SimpleDateFormat(
|
val dateFormat = SimpleDateFormat(
|
||||||
"yyyyMMdd_HHmm",
|
"yyyyMMdd_HHmm",
|
||||||
@@ -428,7 +429,7 @@ fun TocScreen(
|
|||||||
selected = pagerState.currentPage == 0,
|
selected = pagerState.currentPage == 0,
|
||||||
onClick = { scope.launch { pagerState.animateScrollToPage(0) } },
|
onClick = { scope.launch { pagerState.animateScrollToPage(0) } },
|
||||||
text = {
|
text = {
|
||||||
Text(
|
AppText(
|
||||||
text = "目录",
|
text = "目录",
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
@@ -439,7 +440,7 @@ fun TocScreen(
|
|||||||
selected = pagerState.currentPage == 1,
|
selected = pagerState.currentPage == 1,
|
||||||
onClick = { scope.launch { pagerState.animateScrollToPage(1) } },
|
onClick = { scope.launch { pagerState.animateScrollToPage(1) } },
|
||||||
text = {
|
text = {
|
||||||
Text(
|
AppText(
|
||||||
text = "书签",
|
text = "书签",
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
@@ -464,13 +465,13 @@ fun TocScreen(
|
|||||||
onDismissRequest = { showVolumeMenu = false }
|
onDismissRequest = { showVolumeMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("展开所有卷") },
|
text = { AppText("展开所有卷") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.expandAllVolumes(); showVolumeMenu = false
|
viewModel.expandAllVolumes(); showVolumeMenu = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("收起所有卷") },
|
text = { AppText("收起所有卷") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.collapseAllVolumes(); showVolumeMenu = false
|
viewModel.collapseAllVolumes(); showVolumeMenu = false
|
||||||
}
|
}
|
||||||
@@ -482,7 +483,7 @@ fun TocScreen(
|
|||||||
PillHeaderDivider(title = "快速跳转")
|
PillHeaderDivider(title = "快速跳转")
|
||||||
volumeItems.forEach { uiItem ->
|
volumeItems.forEach { uiItem ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(uiItem.title) },
|
text = { AppText(uiItem.title) },
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val targetIndex =
|
val targetIndex =
|
||||||
@@ -541,7 +542,7 @@ fun TocScreen(
|
|||||||
fabMenuExpanded = false
|
fabMenuExpanded = false
|
||||||
},
|
},
|
||||||
icon = { Icon(icon, contentDescription = null) },
|
icon = { Icon(icon, contentDescription = null) },
|
||||||
text = { Text(text = label) }
|
text = { AppText(text = label) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,9 +730,9 @@ fun ChapterItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = item.title,
|
text = item.title,
|
||||||
style = MaterialTheme.typography.bodyMediumEmphasized.copy(fontWeight = FontWeight.Medium),
|
style = LegadoTheme.typography.bodyMediumEmphasized.copy(fontWeight = FontWeight.Medium),
|
||||||
color = textColor,
|
color = textColor,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -739,9 +740,9 @@ fun ChapterItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!item.tag.isNullOrEmpty()) {
|
if (!item.tag.isNullOrEmpty()) {
|
||||||
Text(
|
AppText(
|
||||||
text = item.tag,
|
text = item.tag,
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
style = LegadoTheme.typography.labelSmallEmphasized,
|
||||||
color = detailColor.copy(alpha = 0.8f),
|
color = detailColor.copy(alpha = 0.8f),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@@ -910,11 +911,11 @@ private fun StatusIcon(
|
|||||||
color = Color.Transparent
|
color = Color.Transparent
|
||||||
) {
|
) {
|
||||||
if (wordCount != null) {
|
if (wordCount != null) {
|
||||||
Text(
|
AppText(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp, vertical = 4.dp),
|
.padding(horizontal = 8.dp, vertical = 4.dp),
|
||||||
text = wordCount,
|
text = wordCount,
|
||||||
style = MaterialTheme.typography.labelSmall.copy(fontSize = 9.sp),
|
style = LegadoTheme.typography.labelSmall.copy(fontSize = 9.sp),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,9 @@ import androidx.compose.material3.AlertDialog
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -46,6 +44,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseRuleEvent
|
import io.legado.app.base.BaseRuleEvent
|
||||||
import io.legado.app.data.entities.TxtTocRule
|
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.ActionItem
|
||||||
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
||||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
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.RuleEditFields
|
||||||
import io.legado.app.ui.widget.components.rules.RuleEditSheet
|
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.rules.RuleListScaffold
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@ fun TxtRuleScreen(
|
|||||||
onConfirm = { viewModel.saveImportedRules() },
|
onConfirm = { viewModel.saveImportedRules() },
|
||||||
itemContent = { rule, _ ->
|
itemContent = { rule, _ ->
|
||||||
Column {
|
Column {
|
||||||
Text(rule.name, style = MaterialTheme.typography.titleMedium)
|
AppText(rule.name, style = LegadoTheme.typography.titleMedium)
|
||||||
Text(rule.rule, style = MaterialTheme.typography.bodySmall, maxLines = 1)
|
AppText(rule.rule, style = LegadoTheme.typography.bodySmall, maxLines = 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -212,16 +212,16 @@ fun TxtRuleScreen(
|
|||||||
showDeleteRuleDialog?.let { rule ->
|
showDeleteRuleDialog?.let { rule ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteRuleDialog = null },
|
onDismissRequest = { showDeleteRuleDialog = null },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.del_msg)) },
|
text = { AppText(stringResource(R.string.del_msg)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
viewModel.delete(rule); showDeleteRuleDialog = null
|
viewModel.delete(rule); showDeleteRuleDialog = null
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
||||||
Text(
|
AppText(
|
||||||
stringResource(R.string.cancel)
|
stringResource(R.string.cancel)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ fun TxtRuleScreen(
|
|||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_str)) },
|
text = { AppText(stringResource(R.string.import_str)) },
|
||||||
onClick = { showImportSheet = true; dismiss() },
|
onClick = { showImportSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
@@ -14,11 +13,11 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.ClickableSettingItem
|
||||||
|
import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
|
||||||
|
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -36,7 +35,7 @@ fun ConfigNavScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(stringResource(R.string.setting)) },
|
title = stringResource(R.string.setting),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
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.Permissions
|
||||||
import io.legado.app.lib.permission.PermissionsCompat
|
import io.legado.app.lib.permission.PermissionsCompat
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.filePicker.FilePickerSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem
|
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.InputSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
|
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.isContentScheme
|
||||||
import io.legado.app.utils.takePersistablePermissionSafely
|
import io.legado.app.utils.takePersistablePermissionSafely
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -166,9 +166,7 @@ fun BackupConfigScreen(
|
|||||||
},
|
},
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = stringResource(R.string.backup_restore),
|
||||||
Text(stringResource(R.string.backup_restore))
|
|
||||||
},
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
@@ -387,19 +385,19 @@ fun BackupConfigScreen(
|
|||||||
if (showWebDavAuthDialog) {
|
if (showWebDavAuthDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showWebDavAuthDialog = false },
|
onDismissRequest = { showWebDavAuthDialog = false },
|
||||||
title = { Text(stringResource(R.string.web_dav_account)) },
|
title = { AppText(stringResource(R.string.web_dav_account)) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
TextField(
|
TextField(
|
||||||
value = tempAccount,
|
value = tempAccount,
|
||||||
onValueChange = { tempAccount = it },
|
onValueChange = { tempAccount = it },
|
||||||
label = { Text("账号") }
|
label = { AppText("账号") }
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.padding(8.dp))
|
Spacer(modifier = Modifier.padding(8.dp))
|
||||||
TextField(
|
TextField(
|
||||||
value = tempPassword,
|
value = tempPassword,
|
||||||
onValueChange = { tempPassword = it },
|
onValueChange = { tempPassword = it },
|
||||||
label = { Text("密码") },
|
label = { AppText("密码") },
|
||||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
@@ -432,12 +430,12 @@ fun BackupConfigScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showWebDavAuthDialog = false }) {
|
TextButton(onClick = { showWebDavAuthDialog = false }) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -484,7 +482,7 @@ fun BackupConfigScreen(
|
|||||||
if (showRestoreSheet && backupNames.isNotEmpty()) {
|
if (showRestoreSheet && backupNames.isNotEmpty()) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showRestoreSheet = false },
|
onDismissRequest = { showRestoreSheet = false },
|
||||||
title = { Text(stringResource(R.string.select_restore_file)) },
|
title = { AppText(stringResource(R.string.select_restore_file)) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
backupNames.forEach { name ->
|
backupNames.forEach { name ->
|
||||||
@@ -508,7 +506,7 @@ fun BackupConfigScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}) {
|
}) {
|
||||||
Text(name)
|
AppText(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,7 +514,7 @@ fun BackupConfigScreen(
|
|||||||
confirmButton = {},
|
confirmButton = {},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showRestoreSheet = false }) {
|
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()
|
io.legado.app.help.storage.BackupConfig.saveIgnoreConfig()
|
||||||
showBackupIgnoreDialog = false
|
showBackupIgnoreDialog = false
|
||||||
},
|
},
|
||||||
title = { Text(stringResource(R.string.restore_ignore)) },
|
title = { AppText(stringResource(R.string.restore_ignore)) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
io.legado.app.help.storage.BackupConfig.ignoreTitle.forEachIndexed { index, title ->
|
io.legado.app.help.storage.BackupConfig.ignoreTitle.forEachIndexed { index, title ->
|
||||||
@@ -546,7 +544,7 @@ fun BackupConfigScreen(
|
|||||||
] = checkedItems[index]
|
] = checkedItems[index]
|
||||||
}) {
|
}) {
|
||||||
val isChecked = 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()
|
io.legado.app.help.storage.BackupConfig.saveIgnoreConfig()
|
||||||
showBackupIgnoreDialog = false
|
showBackupIgnoreDialog = false
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
@@ -564,7 +562,7 @@ fun BackupConfigScreen(
|
|||||||
io.legado.app.help.storage.BackupConfig.saveIgnoreConfig()
|
io.legado.app.help.storage.BackupConfig.saveIgnoreConfig()
|
||||||
showBackupIgnoreDialog = false
|
showBackupIgnoreDialog = false
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -573,7 +571,7 @@ fun BackupConfigScreen(
|
|||||||
if (showLoadingDialog) {
|
if (showLoadingDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = {},
|
onDismissRequest = {},
|
||||||
title = { Text(loadingText) },
|
title = { AppText(loadingText) },
|
||||||
confirmButton = {},
|
confirmButton = {},
|
||||||
dismissButton = {}
|
dismissButton = {}
|
||||||
)
|
)
|
||||||
@@ -589,16 +587,16 @@ fun ConfirmDialog(
|
|||||||
) {
|
) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text(title) },
|
title = { AppText(title) },
|
||||||
text = { Text(text) },
|
text = { AppText(text) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = onConfirm) {
|
OutlinedButton(onClick = onConfirm) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismiss) {
|
TextButton(onClick = onDismiss) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import androidx.compose.foundation.shape.CircleShape
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -27,14 +26,14 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.dialog.ColorPickerSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem
|
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.DropdownListSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
|
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
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -52,7 +51,7 @@ fun CoverConfigScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(stringResource(R.string.cover_config)) },
|
title = stringResource(R.string.cover_config),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -36,8 +35,10 @@ import androidx.compose.ui.unit.dp
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.PreferKey
|
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.filePicker.FilePickerSheet
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -69,9 +70,9 @@ fun CoverManageSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 24.dp)
|
.padding(bottom = 24.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.default_cover),
|
text = stringResource(R.string.default_cover),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.compose.material3.Checkbox
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -25,8 +24,10 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.model.BookCover
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.InputSettingItem
|
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 io.legado.app.utils.toastOnUi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -58,9 +59,9 @@ fun CoverRuleConfigSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.cover_rule),
|
text = stringResource(R.string.cover_rule),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ fun CoverRuleConfigSheet(
|
|||||||
checked = enable,
|
checked = enable,
|
||||||
onCheckedChange = { enable = it }
|
onCheckedChange = { enable = it }
|
||||||
)
|
)
|
||||||
Text(text = stringResource(R.string.enable))
|
AppText(text = stringResource(R.string.enable))
|
||||||
}
|
}
|
||||||
|
|
||||||
InputSettingItem(
|
InputSettingItem(
|
||||||
@@ -97,13 +98,16 @@ fun CoverRuleConfigSheet(
|
|||||||
BookCover.delCoverRule()
|
BookCover.delCoverRule()
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.delete), color = MaterialTheme.colorScheme.error)
|
AppText(
|
||||||
|
stringResource(R.string.delete),
|
||||||
|
color = MaterialTheme.colorScheme.error
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
OutlinedButton(onClick = onDismissRequest) {
|
OutlinedButton(onClick = onDismissRequest) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.padding(horizontal = 4.dp))
|
Spacer(modifier = Modifier.padding(horizontal = 4.dp))
|
||||||
@@ -118,7 +122,7 @@ fun CoverRuleConfigSheet(
|
|||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
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.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.CheckboxGroupContainer
|
||||||
import io.legado.app.ui.widget.components.checkBox.CheckboxItem
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
@@ -41,9 +42,9 @@ fun CheckSourceBottomSheet(
|
|||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.padding(bottom = 32.dp)
|
.padding(bottom = 32.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.check_source_config),
|
text = stringResource(R.string.check_source_config),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(vertical = 16.dp)
|
modifier = Modifier.padding(vertical = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ fun CheckSourceBottomSheet(
|
|||||||
horizontalArrangement = Arrangement.End
|
horizontalArrangement = Arrangement.End
|
||||||
) {
|
) {
|
||||||
TextButton(onClick = onDismiss) {
|
TextButton(onClick = onDismiss) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
if (viewModel.saveCheckSourceConfig()) {
|
if (viewModel.saveCheckSourceConfig()) {
|
||||||
@@ -140,7 +141,7 @@ fun CheckSourceBottomSheet(
|
|||||||
Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -24,7 +24,6 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -41,8 +40,10 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.help.DirectLinkUpload
|
import io.legado.app.help.DirectLinkUpload
|
||||||
import io.legado.app.lib.dialogs.selector
|
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.checkBox.CheckboxItem
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
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.GSON
|
||||||
import io.legado.app.utils.fromJsonObject
|
import io.legado.app.utils.fromJsonObject
|
||||||
import io.legado.app.utils.getClipText
|
import io.legado.app.utils.getClipText
|
||||||
@@ -75,9 +76,9 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
) {
|
) {
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.direct_link_upload_config),
|
text = stringResource(R.string.direct_link_upload_config),
|
||||||
style = MaterialTheme.typography.titleLarge
|
style = LegadoTheme.typography.titleLarge
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
@@ -89,7 +90,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("导入默认") },
|
text = { AppText("导入默认") },
|
||||||
leadingIcon = { Icon(Icons.Default.Download, null) },
|
leadingIcon = { Icon(Icons.Default.Download, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -99,7 +100,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.copy_rule)) },
|
text = { AppText(stringResource(R.string.copy_rule)) },
|
||||||
leadingIcon = { Icon(Icons.Default.ContentCopy, null) },
|
leadingIcon = { Icon(Icons.Default.ContentCopy, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -113,7 +114,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.paste_rule)) },
|
text = { AppText(stringResource(R.string.paste_rule)) },
|
||||||
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -141,7 +142,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = viewModel.uploadUrl,
|
value = viewModel.uploadUrl,
|
||||||
onValueChange = { viewModel.uploadUrl = it },
|
onValueChange = { viewModel.uploadUrl = it },
|
||||||
label = { Text(stringResource(R.string.upload_url)) },
|
label = { AppText(stringResource(R.string.upload_url)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = viewModel.downloadUrlRule,
|
value = viewModel.downloadUrlRule,
|
||||||
onValueChange = { viewModel.downloadUrlRule = it },
|
onValueChange = { viewModel.downloadUrlRule = it },
|
||||||
label = { Text(stringResource(R.string.download_url_rule)) },
|
label = { AppText(stringResource(R.string.download_url_rule)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,7 +160,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = viewModel.summary,
|
value = viewModel.summary,
|
||||||
onValueChange = { viewModel.summary = it },
|
onValueChange = { viewModel.summary = it },
|
||||||
label = { Text(stringResource(R.string.summary)) },
|
label = { AppText(stringResource(R.string.summary)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,11 +179,11 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
viewModel.testRule { result -> showTestResult = result }
|
viewModel.testRule { result -> showTestResult = result }
|
||||||
}) {
|
}) {
|
||||||
Text("测试")
|
AppText("测试")
|
||||||
}
|
}
|
||||||
Spacer(Modifier.weight(1f))
|
Spacer(Modifier.weight(1f))
|
||||||
OutlinedButton(onClick = onDismiss) {
|
OutlinedButton(onClick = onDismiss) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
if (viewModel.saveDirectLinkRule()) {
|
if (viewModel.saveDirectLinkRule()) {
|
||||||
@@ -191,7 +192,7 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
context.toastOnUi("请填写完整信息")
|
context.toastOnUi("请填写完整信息")
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,15 +201,15 @@ fun DirectLinkUploadBottomSheet(
|
|||||||
showTestResult?.let { result ->
|
showTestResult?.let { result ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showTestResult = null },
|
onDismissRequest = { showTestResult = null },
|
||||||
title = { Text("Result") },
|
title = { AppText("Result") },
|
||||||
text = { Text(result) },
|
text = { AppText(result) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
showTestResult = null
|
showTestResult = null
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { context.sendToClip(result) }) { Text(stringResource(R.string.copy_text)) }
|
TextButton(onClick = { context.sendToClip(result) }) { AppText(stringResource(R.string.copy_text)) }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -30,8 +29,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.service.WebService
|
import io.legado.app.service.WebService
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.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.InputSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.SliderSettingItem
|
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.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.restart
|
||||||
import io.legado.app.utils.takePersistablePermissionSafely
|
import io.legado.app.utils.takePersistablePermissionSafely
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -83,9 +83,7 @@ fun OtherConfigScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = stringResource(R.string.other_setting),
|
||||||
Text(stringResource(R.string.other_setting))
|
|
||||||
},
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
@@ -200,7 +198,10 @@ fun OtherConfigScreen(
|
|||||||
|
|
||||||
SliderSettingItem(
|
SliderSettingItem(
|
||||||
title = stringResource(R.string.bitmap_cache_size),
|
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(),
|
value = OtherConfig.bitmapCacheSize.toFloat(),
|
||||||
defaultValue = 32f,
|
defaultValue = 32f,
|
||||||
valueRange = 1f..2047f,
|
valueRange = 1f..2047f,
|
||||||
@@ -211,7 +212,10 @@ fun OtherConfigScreen(
|
|||||||
|
|
||||||
SliderSettingItem(
|
SliderSettingItem(
|
||||||
title = stringResource(R.string.image_retain_number),
|
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(),
|
value = OtherConfig.imageRetainNum.toFloat(),
|
||||||
defaultValue = 10f,
|
defaultValue = 10f,
|
||||||
valueRange = 0f..100f,
|
valueRange = 0f..100f,
|
||||||
@@ -220,7 +224,10 @@ fun OtherConfigScreen(
|
|||||||
|
|
||||||
SliderSettingItem(
|
SliderSettingItem(
|
||||||
title = stringResource(R.string.pre_download),
|
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(),
|
value = OtherConfig.preDownloadNum.toFloat(),
|
||||||
defaultValue = 10f,
|
defaultValue = 10f,
|
||||||
valueRange = 0f..100f,
|
valueRange = 0f..100f,
|
||||||
@@ -458,23 +465,23 @@ fun OtherConfigScreen(
|
|||||||
if (showPasswordDialog) {
|
if (showPasswordDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showPasswordDialog = false },
|
onDismissRequest = { showPasswordDialog = false },
|
||||||
title = { Text(stringResource(R.string.set_local_password)) },
|
title = { AppText(stringResource(R.string.set_local_password)) },
|
||||||
text = {
|
text = {
|
||||||
TextField(
|
TextField(
|
||||||
value = tempPassword,
|
value = tempPassword,
|
||||||
onValueChange = { tempPassword = it },
|
onValueChange = { tempPassword = it },
|
||||||
label = { Text("Password") }
|
label = { AppText("Password") }
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
viewModel.setLocalPassword(tempPassword)
|
viewModel.setLocalPassword(tempPassword)
|
||||||
showPasswordDialog = false
|
showPasswordDialog = false
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showPasswordDialog = false }) {
|
TextButton(onClick = { showPasswordDialog = false }) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -492,16 +499,16 @@ fun ConfirmDialog(
|
|||||||
) {
|
) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text(title) },
|
title = { AppText(title) },
|
||||||
text = { Text(text) },
|
text = { AppText(text) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = onConfirm) {
|
OutlinedButton(onClick = onConfirm) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismiss) {
|
TextButton(onClick = onDismiss) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -40,16 +41,16 @@ fun PageKeySheet(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.custom_page_key),
|
text = stringResource(R.string.custom_page_key),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
fontWeight = FontWeight.Companion.Bold
|
fontWeight = FontWeight.Companion.Bold
|
||||||
)
|
)
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = prevKeys,
|
value = prevKeys,
|
||||||
onValueChange = { prevKeys = it },
|
onValueChange = { prevKeys = it },
|
||||||
label = { Text(stringResource(R.string.prev_page_key)) },
|
label = { AppText(stringResource(R.string.prev_page_key)) },
|
||||||
modifier = Modifier.Companion
|
modifier = Modifier.Companion
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onPreviewKeyEvent { event ->
|
.onPreviewKeyEvent { event ->
|
||||||
@@ -72,7 +73,7 @@ fun PageKeySheet(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = nextKeys,
|
value = nextKeys,
|
||||||
onValueChange = { nextKeys = it },
|
onValueChange = { nextKeys = it },
|
||||||
label = { Text(stringResource(R.string.next_page_key)) },
|
label = { AppText(stringResource(R.string.next_page_key)) },
|
||||||
modifier = Modifier.Companion
|
modifier = Modifier.Companion
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onPreviewKeyEvent { event ->
|
.onPreviewKeyEvent { event ->
|
||||||
@@ -92,9 +93,9 @@ fun PageKeySheet(
|
|||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.page_key_set_help),
|
text = stringResource(R.string.page_key_set_help),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ fun PageKeySheet(
|
|||||||
},
|
},
|
||||||
modifier = Modifier.Companion.weight(1f)
|
modifier = Modifier.Companion.weight(1f)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.reset))
|
AppText(stringResource(R.string.reset))
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
@@ -120,7 +121,7 @@ fun PageKeySheet(
|
|||||||
},
|
},
|
||||||
modifier = Modifier.Companion.weight(1f)
|
modifier = Modifier.Companion.weight(1f)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -20,14 +19,14 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.ClickableSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem
|
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.SliderSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
|
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 io.legado.app.utils.canvasrecorder.CanvasRecorderFactory
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@@ -45,9 +44,7 @@ fun ReadConfigScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = stringResource(R.string.read_config),
|
||||||
Text(stringResource(R.string.read_config))
|
|
||||||
},
|
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -31,8 +30,10 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import io.legado.app.R
|
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.filePicker.FilePickerSheet
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@@ -72,9 +73,9 @@ fun BackgroundImageManageSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 24.dp)
|
.padding(bottom = 24.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.background_image),
|
text = stringResource(R.string.background_image),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
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.Launcher5
|
||||||
import io.legado.app.ui.main.Launcher6
|
import io.legado.app.ui.main.Launcher6
|
||||||
import io.legado.app.ui.main.LauncherW
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.getCompatDrawable
|
import io.legado.app.utils.getCompatDrawable
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
|
|
||||||
@@ -61,9 +62,9 @@ fun LauncherIconPickerSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 24.dp)
|
.padding(bottom = 24.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.change_icon),
|
text = stringResource(R.string.change_icon),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ object ThemeConfig {
|
|||||||
|
|
||||||
var paletteStyle by prefDelegate(PreferKey.paletteStyle, "tonalSpot")
|
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 materialVersion by prefDelegate(PreferKey.materialVersion, "material3")
|
||||||
|
|
||||||
var appTheme by prefDelegate(PreferKey.appTheme, "0")
|
var appTheme by prefDelegate(PreferKey.appTheme, "0")
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.ToggleButton
|
import androidx.compose.material3.ToggleButton
|
||||||
import androidx.compose.material3.ToggleButtonDefaults
|
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.help.config.OldThemeConfig
|
||||||
import io.legado.app.lib.theme.ThemeStore
|
import io.legado.app.lib.theme.ThemeStore
|
||||||
import io.legado.app.lib.theme.primaryColor
|
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.ThemeManager
|
||||||
import io.legado.app.ui.theme.ThemeResolver
|
import io.legado.app.ui.theme.ThemeResolver
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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.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.DropdownListSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.SliderSettingItem
|
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.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.postEvent
|
||||||
import io.legado.app.utils.restart
|
import io.legado.app.utils.restart
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
@@ -121,7 +122,7 @@ fun ThemeConfigScreen(
|
|||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(stringResource(R.string.theme_setting)) },
|
title = stringResource(R.string.theme_setting),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
@@ -226,6 +227,13 @@ fun ThemeConfigScreen(
|
|||||||
context.toastOnUi(R.string.restart_to_apply)
|
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(
|
SliderSettingItem(
|
||||||
title = stringResource(R.string.font_scale),
|
title = stringResource(R.string.font_scale),
|
||||||
description = stringResource(
|
description = stringResource(
|
||||||
@@ -478,7 +486,7 @@ fun ThemeConfigScreen(
|
|||||||
if (showRestartDialog) {
|
if (showRestartDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showRestartDialog = false },
|
onDismissRequest = { showRestartDialog = false },
|
||||||
title = { Text(stringResource(R.string.restart_required_message)) },
|
title = { AppText(stringResource(R.string.restart_required_message)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
showRestartDialog = false
|
showRestartDialog = false
|
||||||
@@ -486,7 +494,7 @@ fun ThemeConfigScreen(
|
|||||||
context.restart()
|
context.restart()
|
||||||
}, 100)
|
}, 100)
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
@@ -494,7 +502,7 @@ fun ThemeConfigScreen(
|
|||||||
showRestartDialog = false
|
showRestartDialog = false
|
||||||
context.toastOnUi(R.string.restart_later_message)
|
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 ->
|
saveThemeKey?.let { key ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { saveThemeKey = null },
|
onDismissRequest = { saveThemeKey = null },
|
||||||
title = { Text(stringResource(R.string.theme_name)) },
|
title = { AppText(stringResource(R.string.theme_name)) },
|
||||||
text = {
|
text = {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = themeName,
|
value = themeName,
|
||||||
onValueChange = { themeName = it },
|
onValueChange = { themeName = it },
|
||||||
label = { Text("name") },
|
label = { AppText("name") },
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -566,12 +574,12 @@ fun ThemeConfigScreen(
|
|||||||
saveThemeKey = null
|
saveThemeKey = null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(stringResource(android.R.string.ok))
|
AppText(stringResource(android.R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { saveThemeKey = null }) {
|
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))
|
Spacer(Modifier.size(ToggleButtonDefaults.IconSpacing))
|
||||||
|
|
||||||
Text(text = label)
|
AppText(text = label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -745,9 +753,9 @@ fun ThemeColorButton(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = label,
|
text = label,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,10 @@ import androidx.compose.material.icons.filled.Delete
|
|||||||
import androidx.compose.material.icons.filled.FileDownload
|
import androidx.compose.material.icons.filled.FileDownload
|
||||||
import androidx.compose.material.icons.filled.Share
|
import androidx.compose.material.icons.filled.Share
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -38,8 +36,10 @@ import androidx.core.graphics.toColorInt
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.help.config.OldThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.lib.theme.primaryColor
|
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.card.GlassCard
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
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.GSON
|
||||||
import io.legado.app.utils.getClipText
|
import io.legado.app.utils.getClipText
|
||||||
import io.legado.app.utils.share
|
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),
|
.padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.theme_list),
|
text = stringResource(R.string.theme_list),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -104,13 +104,11 @@ fun ThemeListDialog(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
shape = RoundedCornerShape(20.dp),
|
shape = RoundedCornerShape(20.dp),
|
||||||
colors = CardDefaults.cardColors(
|
containerColor = if (item.primaryColor.toColorInt() == context.primaryColor) {
|
||||||
containerColor = if (item.primaryColor.toColorInt() == context.primaryColor) {
|
MaterialTheme.colorScheme.secondaryContainer
|
||||||
MaterialTheme.colorScheme.secondaryContainer
|
} else {
|
||||||
} else {
|
MaterialTheme.colorScheme.surfaceContainer
|
||||||
MaterialTheme.colorScheme.surfaceContainer
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -129,9 +127,9 @@ fun ThemeListDialog(
|
|||||||
)
|
)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = item.themeName,
|
text = item.themeName,
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = LegadoTheme.typography.bodyLarge,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -161,8 +159,8 @@ fun ThemeListDialog(
|
|||||||
deleteIndex?.let { index ->
|
deleteIndex?.let { index ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { deleteIndex = null },
|
onDismissRequest = { deleteIndex = null },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.sure_del)) },
|
text = { AppText(stringResource(R.string.sure_del)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -171,12 +169,12 @@ fun ThemeListDialog(
|
|||||||
deleteIndex = null
|
deleteIndex = null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(stringResource(android.R.string.ok))
|
AppText(stringResource(android.R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { deleteIndex = null }) {
|
TextButton(onClick = { deleteIndex = null }) {
|
||||||
Text(stringResource(android.R.string.cancel))
|
AppText(stringResource(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -38,6 +37,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.data.entities.DictRule
|
import io.legado.app.data.entities.DictRule
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -69,7 +69,7 @@ fun DictRuleEditSheet(
|
|||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = { Text(stringResource(R.string.dict_rule)) },
|
title = { AppText(stringResource(R.string.dict_rule)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = onDismissRequest) {
|
IconButton(onClick = onDismissRequest) {
|
||||||
Icon(
|
Icon(
|
||||||
@@ -87,7 +87,7 @@ fun DictRuleEditSheet(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.copy_rule)) },
|
text = { AppText(stringResource(R.string.copy_rule)) },
|
||||||
leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) },
|
leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onCopy(
|
onCopy(
|
||||||
@@ -102,7 +102,7 @@ fun DictRuleEditSheet(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.paste_rule)) },
|
text = { AppText(stringResource(R.string.paste_rule)) },
|
||||||
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -132,20 +132,20 @@ fun DictRuleEditSheet(
|
|||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = name,
|
value = name,
|
||||||
onValueChange = { name = it },
|
onValueChange = { name = it },
|
||||||
label = { Text(stringResource(R.string.name)) },
|
label = { AppText(stringResource(R.string.name)) },
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = urlRule,
|
value = urlRule,
|
||||||
onValueChange = { urlRule = it },
|
onValueChange = { urlRule = it },
|
||||||
label = { Text(stringResource(R.string.url_rule)) }
|
label = { AppText(stringResource(R.string.url_rule)) }
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = showRule,
|
value = showRule,
|
||||||
onValueChange = { showRule = it },
|
onValueChange = { showRule = it },
|
||||||
label = { Text(stringResource(R.string.show_rule)) },
|
label = { AppText(stringResource(R.string.show_rule)) },
|
||||||
minLines = 3
|
minLines = 3
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,9 @@ import androidx.compose.material3.AlertDialog
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -46,6 +44,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseRuleEvent
|
import io.legado.app.base.BaseRuleEvent
|
||||||
import io.legado.app.data.entities.DictRule
|
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.ActionItem
|
||||||
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
||||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
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.RuleEditFields
|
||||||
import io.legado.app.ui.widget.components.rules.RuleEditSheet
|
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.rules.RuleListScaffold
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
|
|
||||||
@@ -195,8 +195,8 @@ fun DictRuleScreen(
|
|||||||
onConfirm = { viewModel.saveImportedRules() },
|
onConfirm = { viewModel.saveImportedRules() },
|
||||||
itemContent = { rule, _ ->
|
itemContent = { rule, _ ->
|
||||||
Column {
|
Column {
|
||||||
Text(rule.name, style = MaterialTheme.typography.titleMedium)
|
AppText(rule.name, style = LegadoTheme.typography.titleMedium)
|
||||||
Text(rule.urlRule, style = MaterialTheme.typography.bodySmall, maxLines = 1)
|
AppText(rule.urlRule, style = LegadoTheme.typography.bodySmall, maxLines = 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -211,16 +211,16 @@ fun DictRuleScreen(
|
|||||||
showDeleteRuleDialog?.let { rule ->
|
showDeleteRuleDialog?.let { rule ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteRuleDialog = null },
|
onDismissRequest = { showDeleteRuleDialog = null },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.del_msg)) },
|
text = { AppText(stringResource(R.string.del_msg)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
viewModel.delete(rule); showDeleteRuleDialog = null
|
viewModel.delete(rule); showDeleteRuleDialog = null
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
||||||
Text(
|
AppText(
|
||||||
stringResource(R.string.cancel)
|
stringResource(R.string.cancel)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -310,7 +310,7 @@ fun DictRuleScreen(
|
|||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_str)) },
|
text = { AppText(stringResource(R.string.import_str)) },
|
||||||
onClick = { showImportSheet = true; dismiss() },
|
onClick = { showImportSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ open class MainActivity : BaseComposeActivity() {
|
|||||||
(slideIntoContainer(
|
(slideIntoContainer(
|
||||||
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
||||||
animationSpec = tween(
|
animationSpec = tween(
|
||||||
durationMillis = 520,
|
durationMillis = 480,
|
||||||
easing = FastOutSlowInEasing
|
easing = FastOutSlowInEasing
|
||||||
),
|
),
|
||||||
initialOffset = { fullWidth -> fullWidth }
|
initialOffset = { fullWidth -> fullWidth }
|
||||||
@@ -193,7 +193,7 @@ open class MainActivity : BaseComposeActivity() {
|
|||||||
)) togetherWith (slideOutOfContainer(
|
)) togetherWith (slideOutOfContainer(
|
||||||
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
||||||
animationSpec = tween(
|
animationSpec = tween(
|
||||||
durationMillis = 520,
|
durationMillis = 480,
|
||||||
easing = FastOutSlowInEasing
|
easing = FastOutSlowInEasing
|
||||||
),
|
),
|
||||||
targetOffset = { fullWidth -> fullWidth / 4 }
|
targetOffset = { fullWidth -> fullWidth / 4 }
|
||||||
@@ -208,7 +208,7 @@ open class MainActivity : BaseComposeActivity() {
|
|||||||
(slideIntoContainer(
|
(slideIntoContainer(
|
||||||
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
towards = AnimatedContentTransitionScope.SlideDirection.Start,
|
||||||
animationSpec = tween(
|
animationSpec = tween(
|
||||||
durationMillis = 520,
|
durationMillis = 480,
|
||||||
easing = FastOutSlowInEasing
|
easing = FastOutSlowInEasing
|
||||||
),
|
),
|
||||||
initialOffset = { fullWidth -> -fullWidth / 4 }
|
initialOffset = { fullWidth -> -fullWidth / 4 }
|
||||||
@@ -220,7 +220,7 @@ open class MainActivity : BaseComposeActivity() {
|
|||||||
)) togetherWith (scaleOut(
|
)) togetherWith (scaleOut(
|
||||||
targetScale = 0.8f,
|
targetScale = 0.8f,
|
||||||
animationSpec = tween(
|
animationSpec = tween(
|
||||||
durationMillis = 520,
|
durationMillis = 480,
|
||||||
easing = FastOutSlowInEasing
|
easing = FastOutSlowInEasing
|
||||||
)
|
)
|
||||||
) + fadeOut(
|
) + fadeOut(
|
||||||
|
|||||||
@@ -12,42 +12,57 @@ import androidx.compose.material.icons.outlined.Person
|
|||||||
import androidx.compose.material.icons.outlined.RssFeed
|
import androidx.compose.material.icons.outlined.RssFeed
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import io.legado.app.R
|
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(
|
sealed class MainDestination(
|
||||||
val route: String,
|
val route: String,
|
||||||
@StringRes val labelId: Int,
|
@StringRes val labelId: Int,
|
||||||
val icon: ImageVector,
|
val m3Icon: ImageVector,
|
||||||
val selectedIcon: ImageVector
|
val m3SelectedIcon: ImageVector,
|
||||||
|
val miuixIcon: ImageVector,
|
||||||
|
val miuixSelectedIcon: ImageVector
|
||||||
) {
|
) {
|
||||||
object Bookshelf : MainDestination(
|
object Bookshelf : MainDestination(
|
||||||
"bookshelf",
|
route = "bookshelf",
|
||||||
R.string.bookshelf,
|
labelId = R.string.bookshelf,
|
||||||
Icons.AutoMirrored.Outlined.LibraryBooks,
|
m3Icon = Icons.AutoMirrored.Outlined.LibraryBooks,
|
||||||
Icons.AutoMirrored.Filled.LibraryBooks
|
m3SelectedIcon = Icons.AutoMirrored.Filled.LibraryBooks,
|
||||||
|
miuixIcon = MiuixIcons.Regular.ContactsBook, // 替换为实际的 MIUIX 线框图标
|
||||||
|
miuixSelectedIcon = MiuixIcons.Heavy.ContactsBook // 替换为实际的 MIUIX 填充图标
|
||||||
)
|
)
|
||||||
|
|
||||||
object Explore : MainDestination(
|
object Explore : MainDestination(
|
||||||
"explore",
|
route = "explore",
|
||||||
R.string.discovery,
|
labelId = R.string.discovery,
|
||||||
Icons.Outlined.Explore,
|
m3Icon = Icons.Outlined.Explore,
|
||||||
Icons.Default.Explore
|
m3SelectedIcon = Icons.Default.Explore,
|
||||||
|
miuixIcon = MiuixIcons.Regular.Album,
|
||||||
|
miuixSelectedIcon = MiuixIcons.Heavy.Album
|
||||||
)
|
)
|
||||||
|
|
||||||
object Rss : MainDestination(
|
object Rss : MainDestination(
|
||||||
"rss",
|
route = "rss",
|
||||||
R.string.rss,
|
labelId = R.string.rss,
|
||||||
Icons.Outlined.RssFeed,
|
m3Icon = Icons.Outlined.RssFeed,
|
||||||
Icons.Default.RssFeed
|
m3SelectedIcon = Icons.Default.RssFeed,
|
||||||
|
miuixIcon = MiuixIcons.Regular.Favorites,
|
||||||
|
miuixSelectedIcon = MiuixIcons.Heavy.Favorites
|
||||||
)
|
)
|
||||||
|
|
||||||
object My : MainDestination(
|
object My : MainDestination(
|
||||||
"my",
|
route = "my",
|
||||||
R.string.my,
|
labelId = R.string.my,
|
||||||
Icons.Outlined.Person,
|
m3Icon = Icons.Outlined.Person,
|
||||||
Icons.Default.Person
|
m3SelectedIcon = Icons.Default.Person,
|
||||||
|
miuixIcon = MiuixIcons.Regular.Settings,
|
||||||
|
miuixSelectedIcon = MiuixIcons.Heavy.Settings
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val mainDestinations = listOf(Bookshelf, Explore, Rss, My)
|
val mainDestinations = listOf(Bookshelf, Explore, Rss, My)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,17 +20,12 @@ import androidx.compose.material.icons.filled.Menu
|
|||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material3.Badge
|
import androidx.compose.material3.Badge
|
||||||
import androidx.compose.material3.BadgedBox
|
import androidx.compose.material3.BadgedBox
|
||||||
import androidx.compose.material3.BottomAppBarDefaults
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.WideNavigationRail
|
||||||
import androidx.compose.material3.WideNavigationRailItem
|
import androidx.compose.material3.WideNavigationRailItem
|
||||||
import androidx.compose.material3.WideNavigationRailValue
|
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.info.BookInfoActivity
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.config.mainConfig.MainConfig
|
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.BookshelfScreen
|
||||||
import io.legado.app.ui.main.bookshelf.BookshelfViewModel
|
import io.legado.app.ui.main.bookshelf.BookshelfViewModel
|
||||||
import io.legado.app.ui.main.explore.ExploreScreen
|
import io.legado.app.ui.main.explore.ExploreScreen
|
||||||
import io.legado.app.ui.main.my.MyScreen
|
import io.legado.app.ui.main.my.MyScreen
|
||||||
import io.legado.app.ui.main.rss.RssScreen
|
import io.legado.app.ui.main.rss.RssScreen
|
||||||
import io.legado.app.ui.theme.regularHazeEffect
|
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.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.GlassDefaults
|
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.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.startActivity
|
||||||
import io.legado.app.utils.startActivityForBook
|
import io.legado.app.utils.startActivityForBook
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -151,7 +148,7 @@ fun MainScreen(
|
|||||||
onClick = { context.startActivity<SearchActivity>() },
|
onClick = { context.startActivity<SearchActivity>() },
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
icon = { Icon(Icons.Default.Search, contentDescription = null) },
|
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 ->
|
) { dismiss ->
|
||||||
bookshelfUiState.groups.forEachIndexed { groupIndex, group ->
|
bookshelfUiState.groups.forEachIndexed { groupIndex, group ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(group.groupName) },
|
text = { AppText(group.groupName) },
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
if (pagerState.currentPage != index) {
|
if (pagerState.currentPage != index) {
|
||||||
@@ -224,7 +221,7 @@ fun MainScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
label = if (labelVisibilityMode != "unlabeled") {
|
label = if (labelVisibilityMode != "unlabeled") {
|
||||||
{ Text(stringResource(destination.labelId)) }
|
{ AppText(stringResource(destination.labelId)) }
|
||||||
} else null
|
} else null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -237,103 +234,34 @@ fun MainScreen(
|
|||||||
if (!useRail && MainConfig.showBottomView) {
|
if (!useRail && MainConfig.showBottomView) {
|
||||||
val labelVisibilityMode = MainConfig.labelVisibilityMode
|
val labelVisibilityMode = MainConfig.labelVisibilityMode
|
||||||
val isUnlabeled = labelVisibilityMode == "unlabeled"
|
val isUnlabeled = labelVisibilityMode == "unlabeled"
|
||||||
NavigationBar(
|
|
||||||
|
AppNavigationBar(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.regularHazeEffect(state = hazeState)
|
.regularHazeEffect(state = hazeState)
|
||||||
.height(if (isUnlabeled) 64.dp else 80.dp),
|
.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))
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
val alwaysShowLabel = when (labelVisibilityMode) {
|
val alwaysShowLabel = when (labelVisibilityMode) {
|
||||||
"labeled" -> true
|
"labeled" -> true
|
||||||
"selected" -> false
|
|
||||||
"unlabeled" -> false
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
destinations.forEachIndexed { index, destination ->
|
destinations.forEachIndexed { index, destination ->
|
||||||
val selected = pagerState.targetPage == index
|
val selected = pagerState.targetPage == index
|
||||||
var showGroupMenu by remember { mutableStateOf(false) }
|
AppNavigationBarItem(
|
||||||
val haptic = LocalHapticFeedback.current
|
|
||||||
|
|
||||||
NavigationBarItem(
|
|
||||||
selected = selected,
|
selected = selected,
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch { pagerState.animateScrollToPage(index) }
|
||||||
pagerState.animateScrollToPage(index)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
icon = {
|
labelString = stringResource(destination.labelId),
|
||||||
Box {
|
miuixIcon = if (selected) destination.miuixSelectedIcon else destination.miuixIcon,
|
||||||
NavigationIcon(
|
m3Icon = {
|
||||||
destination = destination,
|
if (selected) destination.m3SelectedIcon else destination.m3Icon
|
||||||
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)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
colors = NavigationBarItemDefaults.colors(
|
m3IndicatorColor = GlassDefaults.glassColor(
|
||||||
indicatorColor = GlassDefaults.glassColor(
|
noBlurColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
noBlurColor = MaterialTheme.colorScheme.secondaryContainer,
|
blurAlpha = GlassDefaults.ThickBlurAlpha
|
||||||
blurAlpha = GlassDefaults.ThickBlurAlpha
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
label = if (labelVisibilityMode != "unlabeled") {
|
m3ShowLabel = !isUnlabeled,
|
||||||
{ Text(stringResource(destination.labelId)) }
|
m3AlwaysShowLabel = alwaysShowLabel
|
||||||
} else null,
|
|
||||||
alwaysShowLabel = alwaysShowLabel
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,10 +314,10 @@ private fun NavigationIcon(
|
|||||||
upBooksCount: Int,
|
upBooksCount: Int,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val icon = if (selected) destination.selectedIcon else destination.icon
|
val icon = if (selected) destination.m3SelectedIcon else destination.m3Icon
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
if (destination == MainDestination.Bookshelf && upBooksCount > 0) {
|
if (destination == MainDestination.Bookshelf && upBooksCount > 0) {
|
||||||
BadgedBox(badge = { Badge { Text(upBooksCount.toString()) } }) {
|
BadgedBox(badge = { Badge { AppText(upBooksCount.toString()) } }) {
|
||||||
Icon(icon, contentDescription = null)
|
Icon(icon, contentDescription = null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.width
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -34,9 +33,11 @@ import androidx.compose.ui.unit.dp
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
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.BookCover
|
||||||
import io.legado.app.ui.widget.components.cover.BookshelfCover
|
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.cover.Cover
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.toTimeAgo
|
import io.legado.app.utils.toTimeAgo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,9 +89,9 @@ fun BookshelfItem(
|
|||||||
) {
|
) {
|
||||||
cover(Modifier.fillMaxSize())
|
cover(Modifier.fillMaxSize())
|
||||||
if (gridStyle == 1) {
|
if (gridStyle == 1) {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
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,
|
color = Color.White,
|
||||||
shadow = Shadow(
|
shadow = Shadow(
|
||||||
color = Color.Black.copy(alpha = 0.5f),
|
color = Color.Black.copy(alpha = 0.5f),
|
||||||
@@ -117,9 +118,9 @@ fun BookshelfItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gridStyle == 0) {
|
if (gridStyle == 0) {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = if (titleSmallFont) MaterialTheme.typography.labelSmall else MaterialTheme.typography.labelMedium,
|
style = if (titleSmallFont) LegadoTheme.typography.labelSmall else LegadoTheme.typography.labelMedium,
|
||||||
maxLines = titleMaxLines,
|
maxLines = titleMaxLines,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
textAlign = if (titleCenter) TextAlign.Center else TextAlign.Start,
|
||||||
@@ -152,16 +153,16 @@ fun BookshelfItem(
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
|
style = LegadoTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
|
||||||
maxLines = if (!isCompact) 2 else 1,
|
maxLines = if (!isCompact) 2 else 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
subTitle?.let {
|
subTitle?.let {
|
||||||
Text(
|
AppText(
|
||||||
text = it,
|
text = it,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.padding(top = 2.dp)
|
modifier = Modifier.padding(top = 2.dp)
|
||||||
@@ -169,9 +170,9 @@ fun BookshelfItem(
|
|||||||
}
|
}
|
||||||
if (!isCompact) {
|
if (!isCompact) {
|
||||||
desc?.let {
|
desc?.let {
|
||||||
Text(
|
AppText(
|
||||||
text = it,
|
text = it,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.padding(top = 2.dp)
|
modifier = Modifier.padding(top = 2.dp)
|
||||||
@@ -372,7 +373,7 @@ fun BookItem(
|
|||||||
isUpdating = isUpdating,
|
isUpdating = isUpdating,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
badgeText = if (BookshelfConfig.showUnread && unreadCount > 0) unreadCount.toString() else null,
|
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,
|
title = book.name,
|
||||||
@@ -384,16 +385,16 @@ fun BookItem(
|
|||||||
desc = stringResource(R.string.read_dur_progress, book.durChapterTitle ?: ""),
|
desc = stringResource(R.string.read_dur_progress, book.durChapterTitle ?: ""),
|
||||||
extra = {
|
extra = {
|
||||||
if (BookshelfConfig.showLastUpdateTime && !book.isLocal) {
|
if (BookshelfConfig.showLastUpdateTime && !book.isLocal) {
|
||||||
Text(
|
AppText(
|
||||||
text = book.latestChapterTime.toTimeAgo(),
|
text = book.latestChapterTime.toTimeAgo(),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = if (layoutMode != 0 || !isCompact) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary,
|
color = if (layoutMode != 0 || !isCompact) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary,
|
||||||
modifier = Modifier.padding(end = 4.dp)
|
modifier = Modifier.padding(end = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
AppText(
|
||||||
text = book.latestChapterTitle ?: "",
|
text = book.latestChapterTitle ?: "",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ data class BookShelfItem(
|
|||||||
val durChapterPos: Int,
|
val durChapterPos: Int,
|
||||||
val latestChapterTitle: String?,
|
val latestChapterTitle: String?,
|
||||||
val latestChapterTime: Long,
|
val latestChapterTime: Long,
|
||||||
|
val lastCheckCount: Int,
|
||||||
val totalChapterNum: Int,
|
val totalChapterNum: Int,
|
||||||
val durChapterIndex: Int,
|
val durChapterIndex: Int,
|
||||||
val type: Int,
|
val type: Int,
|
||||||
@@ -33,5 +34,8 @@ data class BookShelfItem(
|
|||||||
|
|
||||||
val isNotShelf: Boolean get() = (type and BookType.notShelf) > 0
|
val isNotShelf: Boolean get() = (type and BookType.notShelf) > 0
|
||||||
|
|
||||||
|
val isNew: Boolean get() = lastCheckCount > 0
|
||||||
|
|
||||||
|
|
||||||
fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0)
|
fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import androidx.compose.material.icons.filled.TextFormat
|
|||||||
import androidx.compose.material.icons.filled.ViewCompact
|
import androidx.compose.material.icons.filled.ViewCompact
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
@@ -32,10 +31,12 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem
|
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.CompactSliderSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem
|
import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -55,9 +56,9 @@ fun BookshelfConfigSheet(
|
|||||||
.padding(bottom = 32.dp),
|
.padding(bottom = 32.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.bookshelf_layout),
|
text = stringResource(R.string.bookshelf_layout),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(vertical = 16.dp)
|
modifier = Modifier.padding(vertical = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import androidx.compose.material3.SnackbarHostState
|
|||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Tab
|
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.PullToRefreshDefaults
|
||||||
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
||||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
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.manage.BookshelfManageActivity
|
||||||
import io.legado.app.ui.book.search.SearchActivity
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
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.button.SmallOutlinedIconToggleButton
|
||||||
import io.legado.app.ui.widget.components.filePicker.FilePickerSheet
|
import io.legado.app.ui.widget.components.filePicker.FilePickerSheet
|
||||||
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
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.list.ListScaffold
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.menuItem.RoundDropdownMenuItem
|
||||||
|
import io.legado.app.ui.widget.components.tabRow.AdaptiveTabRow
|
||||||
import io.legado.app.utils.readText
|
import io.legado.app.utils.readText
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
@@ -235,37 +237,37 @@ fun BookshelfScreen(
|
|||||||
topBarActions = { },
|
topBarActions = { },
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.add_remote_book)) },
|
text = { AppText(stringResource(R.string.add_remote_book)) },
|
||||||
onClick = { context.startActivity<RemoteBookActivity>(); dismiss() },
|
onClick = { context.startActivity<RemoteBookActivity>(); dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.Wifi, null) }
|
leadingIcon = { Icon(Icons.Default.Wifi, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.book_local)) },
|
text = { AppText(stringResource(R.string.book_local)) },
|
||||||
onClick = { context.startActivity<ImportBookActivity>(); dismiss() },
|
onClick = { context.startActivity<ImportBookActivity>(); dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.Save, null) }
|
leadingIcon = { Icon(Icons.Default.Save, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.update_toc)) },
|
text = { AppText(stringResource(R.string.update_toc)) },
|
||||||
onClick = { viewModel.upToc(uiState.items); dismiss() },
|
onClick = { viewModel.upToc(uiState.items); dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.Refresh, null) }
|
leadingIcon = { Icon(Icons.Default.Refresh, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("布局设置") },
|
text = { AppText("布局设置") },
|
||||||
onClick = { showConfigSheet = true; dismiss() },
|
onClick = { showConfigSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.GridView, null) }
|
leadingIcon = { Icon(Icons.Default.GridView, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.group_manage)) },
|
text = { AppText(stringResource(R.string.group_manage)) },
|
||||||
onClick = { showGroupManageSheet = true; dismiss() },
|
onClick = { showGroupManageSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.Edit, null) }
|
leadingIcon = { Icon(Icons.Default.Edit, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.add_url)) },
|
text = { AppText(stringResource(R.string.add_url)) },
|
||||||
onClick = { showAddUrlDialog = true; dismiss() },
|
onClick = { showAddUrlDialog = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.Link, null) }
|
leadingIcon = { Icon(Icons.Default.Link, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.bookshelf_management)) },
|
text = { AppText(stringResource(R.string.bookshelf_management)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
val groupId =
|
val groupId =
|
||||||
uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
|
uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
|
||||||
@@ -277,7 +279,7 @@ fun BookshelfScreen(
|
|||||||
leadingIcon = { Icon(Icons.Default.Settings, null) }
|
leadingIcon = { Icon(Icons.Default.Settings, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.cache_export)) },
|
text = { AppText(stringResource(R.string.cache_export)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
val groupId =
|
val groupId =
|
||||||
uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
|
uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
|
||||||
@@ -289,7 +291,7 @@ fun BookshelfScreen(
|
|||||||
leadingIcon = { Icon(Icons.Default.Download, null) }
|
leadingIcon = { Icon(Icons.Default.Download, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.export_bookshelf)) },
|
text = { AppText(stringResource(R.string.export_bookshelf)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showExportSheet = true
|
showExportSheet = true
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -297,12 +299,12 @@ fun BookshelfScreen(
|
|||||||
leadingIcon = { Icon(Icons.Default.ImportExport, null) }
|
leadingIcon = { Icon(Icons.Default.ImportExport, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_bookshelf)) },
|
text = { AppText(stringResource(R.string.import_bookshelf)) },
|
||||||
onClick = { showImportSheet = true; dismiss() },
|
onClick = { showImportSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.log)) },
|
text = { AppText(stringResource(R.string.log)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showLogSheet = true
|
showLogSheet = true
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -320,33 +322,19 @@ fun BookshelfScreen(
|
|||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
PrimaryScrollableTabRow(
|
val tabTitles = remember(uiState.groups) {
|
||||||
selectedTabIndex = selectedTabIndex,
|
uiState.groups.map { it.groupName }
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdaptiveTabRow(
|
||||||
|
tabTitles = tabTitles,
|
||||||
|
selectedTabIndex = selectedTabIndex,
|
||||||
|
onTabSelected = { index ->
|
||||||
|
scope.launch { pagerState.animateScrollToPage(index) }
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
if (BookshelfConfig.shouldShowExpandButton) {
|
if (BookshelfConfig.shouldShowExpandButton) {
|
||||||
Box(modifier = Modifier.padding(end = 16.dp)) {
|
Box(modifier = Modifier.padding(end = 16.dp)) {
|
||||||
SmallOutlinedIconToggleButton(
|
SmallOutlinedIconToggleButton(
|
||||||
@@ -361,7 +349,7 @@ fun BookshelfScreen(
|
|||||||
) { dismiss ->
|
) { dismiss ->
|
||||||
uiState.groups.forEachIndexed { index, group ->
|
uiState.groups.forEachIndexed { index, group ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(group.groupName) },
|
text = { AppText(group.groupName) },
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch { pagerState.animateScrollToPage(index) }
|
scope.launch { pagerState.animateScrollToPage(index) }
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -565,10 +553,10 @@ fun BookshelfScreen(
|
|||||||
) {
|
) {
|
||||||
CircularProgressIndicator()
|
CircularProgressIndicator()
|
||||||
uiState.loadingText?.let {
|
uiState.loadingText?.let {
|
||||||
Text(
|
AppText(
|
||||||
text = it,
|
text = it,
|
||||||
modifier = Modifier.padding(top = 16.dp),
|
modifier = Modifier.padding(top = 16.dp),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = LegadoTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
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.data.entities.BookGroup
|
||||||
import io.legado.app.ui.book.group.GroupEditContent
|
import io.legado.app.ui.book.group.GroupEditContent
|
||||||
import io.legado.app.ui.book.group.GroupViewModel
|
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.card.ReorderableSelectionItem
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
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 io.legado.app.utils.move
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
@@ -104,9 +105,9 @@ fun GroupManageSheet(
|
|||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = stringResource(R.string.group_manage),
|
text = stringResource(R.string.group_manage),
|
||||||
style = MaterialTheme.typography.titleLarge
|
style = LegadoTheme.typography.titleLarge
|
||||||
)
|
)
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
editingGroup = null
|
editingGroup = null
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ import androidx.compose.material3.ListItemDefaults
|
|||||||
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
|
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedCard
|
import androidx.compose.material3.OutlinedCard
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
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.search.SearchScope
|
||||||
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
|
||||||
import io.legado.app.ui.login.SourceLoginActivity
|
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.GlassCard
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
import io.legado.app.ui.widget.components.card.TextCard
|
||||||
import io.legado.app.ui.widget.components.divider.PillHeaderDivider
|
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.MenuItemIcon
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.menuItem.RoundDropdownMenuItem
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||||
@@ -148,13 +152,13 @@ fun ExploreScreen(
|
|||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Group) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Group) },
|
||||||
text = { Text(stringResource(R.string.all)) },
|
text = { AppText(stringResource(R.string.all)) },
|
||||||
onClick = { viewModel.setGroup(""); dismiss() }
|
onClick = { viewModel.setGroup(""); dismiss() }
|
||||||
)
|
)
|
||||||
uiState.groups.forEach { group ->
|
uiState.groups.forEach { group ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) },
|
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) },
|
||||||
text = { Text(group) },
|
text = { AppText(group) },
|
||||||
onClick = { viewModel.setGroup(group); dismiss() }
|
onClick = { viewModel.setGroup(group); dismiss() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -274,19 +278,19 @@ fun ExploreScreen(
|
|||||||
sourceToDelete?.let { source ->
|
sourceToDelete?.let { source ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { sourceToDelete = null },
|
onDismissRequest = { sourceToDelete = null },
|
||||||
title = { Text(stringResource(R.string.draw)) },
|
title = { AppText(stringResource(R.string.draw)) },
|
||||||
text = { Text(stringResource(R.string.sure_del) + "\n" + source.bookSourceName) },
|
text = { AppText(stringResource(R.string.sure_del) + "\n" + source.bookSourceName) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
viewModel.deleteSource(source)
|
viewModel.deleteSource(source)
|
||||||
sourceToDelete = null
|
sourceToDelete = null
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.yes))
|
AppText(stringResource(R.string.yes))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { sourceToDelete = null }) {
|
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) }
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
val rotation by animateFloatAsState(if (isExpanded) 90f else 0f, label = "rotation")
|
val rotation by animateFloatAsState(if (isExpanded) 90f else 0f, label = "rotation")
|
||||||
|
|
||||||
|
val composeEngine = ThemeResolver.isMiuixEngine(composeEngine)
|
||||||
val containerColor by animateColorAsState(
|
val containerColor by animateColorAsState(
|
||||||
targetValue = if (isExpanded)
|
targetValue = if (isExpanded)
|
||||||
MaterialTheme.colorScheme.secondaryContainer
|
if (composeEngine) MiuixTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.secondaryContainer
|
||||||
else
|
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),
|
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
||||||
label = "CardColor"
|
label = "CardColor"
|
||||||
)
|
)
|
||||||
@@ -358,7 +373,7 @@ fun ExploreSourceHeader(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp),
|
.padding(horizontal = 16.dp, vertical = 4.dp),
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.shapes.medium,
|
||||||
colors = CardDefaults.cardColors(containerColor = containerColor),
|
containerColor = containerColor
|
||||||
) {
|
) {
|
||||||
ListItem(
|
ListItem(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -371,14 +386,10 @@ fun ExploreSourceHeader(
|
|||||||
containerColor = Color.Transparent
|
containerColor = Color.Transparent
|
||||||
),
|
),
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
AppText(
|
||||||
text = item.bookSourceName,
|
text = item.bookSourceName,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
color = if (isExpanded) {
|
color = contentColor
|
||||||
MaterialTheme.colorScheme.primary
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.onSurface
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
@@ -401,29 +412,29 @@ fun ExploreSourceHeader(
|
|||||||
PillHeaderDivider(title = item.bookSourceName)
|
PillHeaderDivider(title = item.bookSourceName)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) },
|
leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) },
|
||||||
text = { Text(stringResource(R.string.to_top)) },
|
text = { AppText(stringResource(R.string.to_top)) },
|
||||||
onClick = { onTop(); showMenu = false }
|
onClick = { onTop(); showMenu = false }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Edit) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Edit) },
|
||||||
text = { Text(stringResource(R.string.edit)) },
|
text = { AppText(stringResource(R.string.edit)) },
|
||||||
onClick = { onEdit(); showMenu = false }
|
onClick = { onEdit(); showMenu = false }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Search) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Search) },
|
||||||
text = { Text(stringResource(R.string.search)) },
|
text = { AppText(stringResource(R.string.search)) },
|
||||||
onClick = { onSearch(); showMenu = false }
|
onClick = { onSearch(); showMenu = false }
|
||||||
)
|
)
|
||||||
if (item.hasLoginUrl) {
|
if (item.hasLoginUrl) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
||||||
text = { Text(stringResource(R.string.login)) },
|
text = { AppText(stringResource(R.string.login)) },
|
||||||
onClick = { onLogin(); showMenu = false }
|
onClick = { onLogin(); showMenu = false }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Refresh) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Refresh) },
|
||||||
text = { Text(stringResource(R.string.refresh)) },
|
text = { AppText(stringResource(R.string.refresh)) },
|
||||||
onClick = { onRefresh(); showMenu = false }
|
onClick = { onRefresh(); showMenu = false }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
@@ -434,7 +445,7 @@ fun ExploreSourceHeader(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Text(
|
AppText(
|
||||||
stringResource(R.string.delete),
|
stringResource(R.string.delete),
|
||||||
color = MaterialTheme.colorScheme.error
|
color = MaterialTheme.colorScheme.error
|
||||||
)
|
)
|
||||||
@@ -455,7 +466,7 @@ fun ExploreStickyCard(
|
|||||||
TextCard(
|
TextCard(
|
||||||
text = item.bookSourceName,
|
text = item.bookSourceName,
|
||||||
backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
textStyle = MaterialTheme.typography.labelLarge,
|
textStyle = LegadoTheme.typography.labelLarge,
|
||||||
horizontalPadding = 8.dp,
|
horizontalPadding = 8.dp,
|
||||||
verticalPadding = 6.dp,
|
verticalPadding = 6.dp,
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
@@ -479,10 +490,8 @@ fun ExploreKindItem(
|
|||||||
GlassCard(
|
GlassCard(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
shape = shape,
|
shape = shape,
|
||||||
colors = CardDefaults.cardColors(
|
containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f),
|
||||||
containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f),
|
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
|
||||||
),
|
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
KindText(kind)
|
KindText(kind)
|
||||||
@@ -506,12 +515,12 @@ fun ExploreKindItem(
|
|||||||
private fun KindText(
|
private fun KindText(
|
||||||
kind: ExploreKind
|
kind: ExploreKind
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = kind.title,
|
text = kind.title,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 8.dp),
|
.padding(vertical = 8.dp),
|
||||||
style = MaterialTheme.typography.labelMediumEmphasized,
|
style = LegadoTheme.typography.labelMediumEmphasized,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
package io.legado.app.ui.main.my
|
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.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBars
|
import androidx.compose.foundation.layout.systemBars
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
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.LibraryBooks
|
||||||
import androidx.compose.material.icons.automirrored.filled.Rule
|
import androidx.compose.material.icons.automirrored.filled.Rule
|
||||||
import androidx.compose.material.icons.filled.Bookmark
|
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.FindReplace
|
||||||
import androidx.compose.material.icons.filled.Folder
|
import androidx.compose.material.icons.filled.Folder
|
||||||
import androidx.compose.material.icons.filled.History
|
import androidx.compose.material.icons.filled.History
|
||||||
import androidx.compose.material.icons.filled.Info
|
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.Settings
|
||||||
import androidx.compose.material.icons.filled.Source
|
import androidx.compose.material.icons.filled.Source
|
||||||
import androidx.compose.material.icons.filled.Web
|
import androidx.compose.material.icons.filled.Web
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
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.dict.rule.DictRuleActivity
|
||||||
import io.legado.app.ui.file.FileManageActivity
|
import io.legado.app.ui.file.FileManageActivity
|
||||||
import io.legado.app.ui.replace.ReplaceRuleActivity
|
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.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.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)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@@ -70,11 +79,7 @@ fun MyScreen(
|
|||||||
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top),
|
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = {
|
title = stringResource(R.string.my),
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.my)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { onNavigate(PrefClickEvent.ShowMd("appHelp", "xxx")) }
|
onClick = { onNavigate(PrefClickEvent.ShowMd("appHelp", "xxx")) }
|
||||||
@@ -99,52 +104,21 @@ fun MyScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
SplicedColumnGroup(
|
SplicedColumnGroup(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.adaptiveHorizontalPadding(),
|
||||||
title = ""
|
title = ""
|
||||||
) {
|
) {
|
||||||
SettingItem(
|
WebServiceSettingBlock(
|
||||||
title = stringResource(R.string.web_service),
|
uiState = uiState,
|
||||||
description = if (uiState.isWebServiceRun)
|
viewModel = viewModel,
|
||||||
uiState.webServiceAddress
|
onNavigate = onNavigate
|
||||||
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 = { }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SplicedColumnGroup(
|
SplicedColumnGroup(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.adaptiveHorizontalPadding(),
|
||||||
title = "规则"
|
title = "规则"
|
||||||
) {
|
) {
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.book_source_manage),
|
title = stringResource(R.string.book_source_manage),
|
||||||
description = stringResource(R.string.book_source_manage_desc),
|
description = stringResource(R.string.book_source_manage_desc),
|
||||||
imageVector = Icons.Default.Source,
|
imageVector = Icons.Default.Source,
|
||||||
@@ -154,7 +128,7 @@ fun MyScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.replace_purify),
|
title = stringResource(R.string.replace_purify),
|
||||||
imageVector = Icons.Default.FindReplace,
|
imageVector = Icons.Default.FindReplace,
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -163,7 +137,7 @@ fun MyScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.txt_toc_rule),
|
title = stringResource(R.string.txt_toc_rule),
|
||||||
imageVector = Icons.AutoMirrored.Filled.Rule,
|
imageVector = Icons.AutoMirrored.Filled.Rule,
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -172,7 +146,7 @@ fun MyScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.dict_rule),
|
title = stringResource(R.string.dict_rule),
|
||||||
imageVector = Icons.AutoMirrored.Filled.LibraryBooks,
|
imageVector = Icons.AutoMirrored.Filled.LibraryBooks,
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -184,44 +158,44 @@ fun MyScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SplicedColumnGroup(
|
SplicedColumnGroup(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.adaptiveHorizontalPadding(),
|
||||||
title = stringResource(R.string.other)) {
|
title = stringResource(R.string.other)) {
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.setting),
|
title = stringResource(R.string.setting),
|
||||||
imageVector = Icons.Default.Settings,
|
imageVector = Icons.Default.Settings,
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenSettings()
|
onOpenSettings()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.bookmark),
|
title = stringResource(R.string.bookmark),
|
||||||
imageVector = Icons.Default.Bookmark,
|
imageVector = Icons.Default.Bookmark,
|
||||||
onClick = {
|
onClick = {
|
||||||
onNavigate(PrefClickEvent.StartActivity(AllBookmarkActivity::class.java))
|
onNavigate(PrefClickEvent.StartActivity(AllBookmarkActivity::class.java))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.read_record),
|
title = stringResource(R.string.read_record),
|
||||||
imageVector = Icons.Default.History,
|
imageVector = Icons.Default.History,
|
||||||
onClick = {
|
onClick = {
|
||||||
onNavigate(PrefClickEvent.StartActivity(ReadRecordActivity::class.java))
|
onNavigate(PrefClickEvent.StartActivity(ReadRecordActivity::class.java))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.file_manage),
|
title = stringResource(R.string.file_manage),
|
||||||
imageVector = Icons.Default.Folder,
|
imageVector = Icons.Default.Folder,
|
||||||
onClick = {
|
onClick = {
|
||||||
onNavigate(PrefClickEvent.StartActivity(FileManageActivity::class.java))
|
onNavigate(PrefClickEvent.StartActivity(FileManageActivity::class.java))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.about),
|
title = stringResource(R.string.about),
|
||||||
imageVector = Icons.Default.Info,
|
imageVector = Icons.Default.Info,
|
||||||
onClick = {
|
onClick = {
|
||||||
onNavigate(PrefClickEvent.StartActivity(AboutActivity::class.java))
|
onNavigate(PrefClickEvent.StartActivity(AboutActivity::class.java))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
SettingItem(
|
ClickableSettingItem(
|
||||||
title = stringResource(R.string.exit),
|
title = stringResource(R.string.exit),
|
||||||
imageVector = Icons.AutoMirrored.Filled.ExitToApp,
|
imageVector = Icons.AutoMirrored.Filled.ExitToApp,
|
||||||
onClick = {
|
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))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import androidx.compose.material.icons.filled.VerticalAlignTop
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
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.edit.RssSourceEditActivity
|
||||||
import io.legado.app.ui.rss.source.manage.RssSourceActivity
|
import io.legado.app.ui.rss.source.manage.RssSourceActivity
|
||||||
import io.legado.app.ui.rss.subscription.RuleSubActivity
|
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.SourceIcon
|
||||||
import io.legado.app.ui.widget.components.button.TopBarActionButton
|
import io.legado.app.ui.widget.components.button.TopBarActionButton
|
||||||
import io.legado.app.ui.widget.components.divider.PillDivider
|
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.MenuItemIcon
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.menuItem.RoundDropdownMenuItem
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.openUrl
|
import io.legado.app.utils.openUrl
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -135,12 +136,12 @@ fun RssScreen(
|
|||||||
dismiss()
|
dismiss()
|
||||||
},
|
},
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Settings) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Settings) },
|
||||||
text = { Text("订阅源管理") }
|
text = { AppText("订阅源管理") }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Group) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Group) },
|
||||||
text = { Text(stringResource(R.string.all)) },
|
text = { AppText(stringResource(R.string.all)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setGroup("")
|
viewModel.setGroup("")
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -149,7 +150,7 @@ fun RssScreen(
|
|||||||
uiState.groups.forEach { group ->
|
uiState.groups.forEach { group ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) },
|
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Outlined.Label) },
|
||||||
text = { Text(group) },
|
text = { AppText(group) },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setGroup(group)
|
viewModel.setGroup(group)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -188,8 +189,8 @@ fun RssScreen(
|
|||||||
sourceToDelete?.let { source ->
|
sourceToDelete?.let { source ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { sourceToDelete = null },
|
onDismissRequest = { sourceToDelete = null },
|
||||||
title = { Text(stringResource(R.string.draw)) },
|
title = { AppText(stringResource(R.string.draw)) },
|
||||||
text = { Text(stringResource(R.string.sure_del) + "\n" + source.sourceName) },
|
text = { AppText(stringResource(R.string.sure_del) + "\n" + source.sourceName) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -197,12 +198,12 @@ fun RssScreen(
|
|||||||
sourceToDelete = null
|
sourceToDelete = null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.yes))
|
AppText(stringResource(R.string.yes))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { sourceToDelete = null }) {
|
TextButton(onClick = { sourceToDelete = null }) {
|
||||||
Text(stringResource(R.string.no))
|
AppText(stringResource(R.string.no))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -246,7 +247,7 @@ fun RssSourceGridItem(
|
|||||||
PillHeaderDivider(title = source.sourceName)
|
PillHeaderDivider(title = source.sourceName)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) },
|
leadingIcon = { MenuItemIcon(Icons.Default.VerticalAlignTop) },
|
||||||
text = { Text(stringResource(R.string.to_top)) },
|
text = { AppText(stringResource(R.string.to_top)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onTop()
|
onTop()
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -254,7 +255,7 @@ fun RssSourceGridItem(
|
|||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Edit) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Edit) },
|
||||||
text = { Text(stringResource(R.string.edit)) },
|
text = { AppText(stringResource(R.string.edit)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onEdit()
|
onEdit()
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -263,7 +264,7 @@ fun RssSourceGridItem(
|
|||||||
if (!source.loginUrl.isNullOrBlank()) {
|
if (!source.loginUrl.isNullOrBlank()) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
||||||
text = { Text(stringResource(R.string.login)) },
|
text = { AppText(stringResource(R.string.login)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onLogin()
|
onLogin()
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -272,7 +273,7 @@ fun RssSourceGridItem(
|
|||||||
}
|
}
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
leadingIcon = { MenuItemIcon(Icons.Default.Close) },
|
leadingIcon = { MenuItemIcon(Icons.Default.Close) },
|
||||||
text = { Text(stringResource(R.string.disable_source)) },
|
text = { AppText(stringResource(R.string.disable_source)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onDisable()
|
onDisable()
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -286,7 +287,7 @@ fun RssSourceGridItem(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
Text(
|
AppText(
|
||||||
stringResource(R.string.delete),
|
stringResource(R.string.delete),
|
||||||
color = MaterialTheme.colorScheme.error
|
color = MaterialTheme.colorScheme.error
|
||||||
)
|
)
|
||||||
@@ -299,9 +300,9 @@ fun RssSourceGridItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = source.sourceName,
|
text = source.sourceName,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
@@ -26,14 +25,10 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
|||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.LoadingIndicator
|
import androidx.compose.material3.LoadingIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.PrimaryScrollableTabRow
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Tab
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TooltipAnchorPosition
|
import androidx.compose.material3.TooltipAnchorPosition
|
||||||
import androidx.compose.material3.TooltipBox
|
import androidx.compose.material3.TooltipBox
|
||||||
@@ -50,20 +45,19 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.platform.ClipEntry
|
import androidx.compose.ui.platform.ClipEntry
|
||||||
import androidx.compose.ui.platform.LocalClipboard
|
import androidx.compose.ui.platform.LocalClipboard
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseRuleEvent
|
import io.legado.app.base.BaseRuleEvent
|
||||||
import io.legado.app.data.entities.ReplaceRule
|
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.ActionItem
|
||||||
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
||||||
import io.legado.app.ui.widget.components.GroupManageBottomSheet
|
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.lazylist.FastScrollLazyColumn
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.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 kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
@@ -207,9 +203,9 @@ fun ReplaceRuleScreen(
|
|||||||
topBarActions = {},
|
topBarActions = {},
|
||||||
itemContent = { rule, _ ->
|
itemContent = { rule, _ ->
|
||||||
Column {
|
Column {
|
||||||
Text(rule.name, style = MaterialTheme.typography.titleMedium)
|
AppText(rule.name, style = LegadoTheme.typography.titleMedium)
|
||||||
if (!rule.group.isNullOrBlank()) {
|
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 ->
|
showDeleteRuleDialog?.let { rule ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteRuleDialog = null },
|
onDismissRequest = { showDeleteRuleDialog = null },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.del_msg)) },
|
text = { AppText(stringResource(R.string.del_msg)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
viewModel.delete(rule); showDeleteRuleDialog = null
|
viewModel.delete(rule); showDeleteRuleDialog = null
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
||||||
Text(
|
AppText(
|
||||||
stringResource(R.string.cancel)
|
stringResource(R.string.cancel)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -347,39 +343,21 @@ fun ReplaceRuleScreen(
|
|||||||
},
|
},
|
||||||
bottomContent = {
|
bottomContent = {
|
||||||
if (tabItems.size > 1) {
|
if (tabItems.size > 1) {
|
||||||
PrimaryScrollableTabRow(
|
AdaptiveTabRow(
|
||||||
selectedTabIndex = selectedTabIndex.coerceAtMost(tabItems.size - 1)
|
tabTitles = tabItems,
|
||||||
.coerceAtLeast(0),
|
selectedTabIndex = selectedTabIndex,
|
||||||
edgePadding = 0.dp,
|
onTabSelected = { index ->
|
||||||
divider = {},
|
selectedTabIndex = index
|
||||||
containerColor = Color.Transparent,
|
viewModel.setGroup(tabItems[index])
|
||||||
) {
|
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
TooltipBox(
|
TooltipBox(
|
||||||
positionProvider =
|
positionProvider =
|
||||||
TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
|
TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
|
||||||
tooltip = { PlainTooltip { Text("Localized description") } },
|
tooltip = { PlainTooltip { AppText("Localized description") } },
|
||||||
state = rememberTooltipState(),
|
state = rememberTooltipState(),
|
||||||
) {
|
) {
|
||||||
with(sharedTransitionScope) {
|
with(sharedTransitionScope) {
|
||||||
@@ -406,29 +384,29 @@ fun ReplaceRuleScreen(
|
|||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_str)) },
|
text = { AppText(stringResource(R.string.import_str)) },
|
||||||
onClick = { showImportSheet = true; dismiss() },
|
onClick = { showImportSheet = true; dismiss() },
|
||||||
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
leadingIcon = { Icon(Icons.Default.FileOpen, null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("分组管理") },
|
text = { AppText("分组管理") },
|
||||||
onClick = { showGroupManageSheet = true; dismiss() }
|
onClick = { showGroupManageSheet = true; dismiss() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("帮助") },
|
text = { AppText("帮助") },
|
||||||
onClick = { /*TODO*/ dismiss() }
|
onClick = { /*TODO*/ dismiss() }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("旧的在前") },
|
text = { AppText("旧的在前") },
|
||||||
onClick = { viewModel.setSortMode("asc"); dismiss() }
|
onClick = { viewModel.setSortMode("asc"); dismiss() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("新的在前") },
|
text = { AppText("新的在前") },
|
||||||
onClick = { viewModel.setSortMode("desc"); dismiss() }
|
onClick = { viewModel.setSortMode("desc"); dismiss() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("名称升序") },
|
text = { AppText("名称升序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setSortMode("name_asc")
|
viewModel.setSortMode("name_asc")
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -438,7 +416,7 @@ fun ReplaceRuleScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("名称降序") },
|
text = { AppText("名称降序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setSortMode("name_desc")
|
viewModel.setSortMode("name_desc")
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -496,15 +474,15 @@ fun ReplaceRuleScreen(
|
|||||||
),
|
),
|
||||||
dropdownContent = { dismiss ->
|
dropdownContent = { dismiss ->
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("移至顶部") },
|
text = { AppText("移至顶部") },
|
||||||
onClick = { viewModel.toTop(ui.rule); dismiss() }
|
onClick = { viewModel.toTop(ui.rule); dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("移至底部") },
|
text = { AppText("移至底部") },
|
||||||
onClick = { viewModel.toBottom(ui.rule); dismiss() }
|
onClick = { viewModel.toBottom(ui.rule); dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("删除") },
|
text = { AppText("删除") },
|
||||||
onClick = { showDeleteRuleDialog = ui.rule; dismiss() }
|
onClick = { showDeleteRuleDialog = ui.rule; dismiss() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TooltipAnchorPosition
|
import androidx.compose.material3.TooltipAnchorPosition
|
||||||
import androidx.compose.material3.TooltipBox
|
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.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
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.AlertButton
|
||||||
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
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
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -119,7 +119,7 @@ fun ReplaceEditScreen(
|
|||||||
.imePadding(),
|
.imePadding(),
|
||||||
topBar = {
|
topBar = {
|
||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(if (state.id > 0) "编辑替换规则" else "新增替换规则") },
|
title = if (state.id > 0) "编辑替换规则" else "新增替换规则",
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
@@ -143,14 +143,14 @@ fun ReplaceEditScreen(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("复制规则") },
|
text = { AppText("复制规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
viewModel.copyRule()
|
viewModel.copyRule()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text("粘贴规则") },
|
text = { AppText("粘贴规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
viewModel.pasteRule(onSuccess = {})
|
viewModel.pasteRule(onSuccess = {})
|
||||||
@@ -167,7 +167,7 @@ fun ReplaceEditScreen(
|
|||||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
||||||
TooltipAnchorPosition.Above
|
TooltipAnchorPosition.Above
|
||||||
),
|
),
|
||||||
tooltip = { PlainTooltip { Text("添加") } },
|
tooltip = { PlainTooltip { AppText("添加") } },
|
||||||
state = rememberTooltipState(),
|
state = rememberTooltipState(),
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
@@ -214,7 +214,7 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.name,
|
value = state.name,
|
||||||
onValueChange = viewModel::onNameChange,
|
onValueChange = viewModel::onNameChange,
|
||||||
label = { Text("规则名称") },
|
label = { AppText("规则名称") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
@@ -234,8 +234,8 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.pattern,
|
value = state.pattern,
|
||||||
onValueChange = viewModel::onPatternChange,
|
onValueChange = viewModel::onPatternChange,
|
||||||
label = { Text("匹配规则") },
|
label = { AppText("匹配规则") },
|
||||||
placeholder = { Text("输入正则表达式或关键字") },
|
placeholder = { AppText("输入正则表达式或关键字") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
@@ -247,8 +247,8 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.replacement,
|
value = state.replacement,
|
||||||
onValueChange = viewModel::onReplacementChange,
|
onValueChange = viewModel::onReplacementChange,
|
||||||
label = { Text("替换为") },
|
label = { AppText("替换为") },
|
||||||
placeholder = { Text("输入替换内容或捕获组") },
|
placeholder = { AppText("输入替换内容或捕获组") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
@@ -265,7 +265,7 @@ fun ReplaceEditScreen(
|
|||||||
FilterChip(
|
FilterChip(
|
||||||
selected = state.scopeTitle,
|
selected = state.scopeTitle,
|
||||||
onClick = { viewModel.onScopeTitleChange(!state.scopeTitle) },
|
onClick = { viewModel.onScopeTitleChange(!state.scopeTitle) },
|
||||||
label = { Text("标题") },
|
label = { AppText("标题") },
|
||||||
leadingIcon = if (state.scopeTitle) {
|
leadingIcon = if (state.scopeTitle) {
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
@@ -282,7 +282,7 @@ fun ReplaceEditScreen(
|
|||||||
FilterChip(
|
FilterChip(
|
||||||
selected = state.scopeContent,
|
selected = state.scopeContent,
|
||||||
onClick = { viewModel.onScopeContentChange(!state.scopeContent) },
|
onClick = { viewModel.onScopeContentChange(!state.scopeContent) },
|
||||||
label = { Text("内容") },
|
label = { AppText("内容") },
|
||||||
leadingIcon = if (state.scopeContent) {
|
leadingIcon = if (state.scopeContent) {
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
@@ -299,7 +299,7 @@ fun ReplaceEditScreen(
|
|||||||
FilterChip(
|
FilterChip(
|
||||||
selected = state.isRegex,
|
selected = state.isRegex,
|
||||||
onClick = { viewModel.onRegexChange(!state.isRegex) },
|
onClick = { viewModel.onRegexChange(!state.isRegex) },
|
||||||
label = { Text("使用正则") },
|
label = { AppText("使用正则") },
|
||||||
leadingIcon = if (state.isRegex) {
|
leadingIcon = if (state.isRegex) {
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
@@ -316,8 +316,8 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.scope,
|
value = state.scope,
|
||||||
onValueChange = viewModel::onScopeChange,
|
onValueChange = viewModel::onScopeChange,
|
||||||
label = { Text("特定范围") },
|
label = { AppText("特定范围") },
|
||||||
placeholder = { Text("指定规则适用的范围") },
|
placeholder = { AppText("指定规则适用的范围") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
@@ -329,8 +329,8 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.excludeScope,
|
value = state.excludeScope,
|
||||||
onValueChange = viewModel::onExcludeScopeChange,
|
onValueChange = viewModel::onExcludeScopeChange,
|
||||||
label = { Text("排除范围") },
|
label = { AppText("排除范围") },
|
||||||
placeholder = { Text("指定规则不适用的范围") },
|
placeholder = { AppText("指定规则不适用的范围") },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
@@ -342,8 +342,8 @@ fun ReplaceEditScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.timeout,
|
value = state.timeout,
|
||||||
onValueChange = viewModel::onTimeoutChange,
|
onValueChange = viewModel::onTimeoutChange,
|
||||||
label = { Text("超时 (ms)") },
|
label = { AppText("超时 (ms)") },
|
||||||
placeholder = { Text("3000") },
|
placeholder = { AppText("3000") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -383,8 +383,8 @@ fun GroupSelector(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = currentGroup,
|
value = currentGroup,
|
||||||
onValueChange = onGroupChange,
|
onValueChange = onGroupChange,
|
||||||
label = { Text("分组") },
|
label = { AppText("分组") },
|
||||||
placeholder = { Text("默认") },
|
placeholder = { AppText("默认") },
|
||||||
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
|
||||||
colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),
|
colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -400,7 +400,7 @@ fun GroupSelector(
|
|||||||
) {
|
) {
|
||||||
allGroups.forEach { selectionOption ->
|
allGroups.forEach { selectionOption ->
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(selectionOption) },
|
text = { AppText(selectionOption) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onGroupChange(selectionOption)
|
onGroupChange(selectionOption)
|
||||||
expanded = false
|
expanded = false
|
||||||
@@ -426,9 +426,9 @@ fun ManageGroupDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text("分组管理") },
|
title = { AppText("分组管理") },
|
||||||
text = {
|
text = {
|
||||||
if (groups.isEmpty()) Text("暂无其他分组")
|
if (groups.isEmpty()) AppText("暂无其他分组")
|
||||||
else Column(
|
else Column(
|
||||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
@@ -448,7 +448,7 @@ fun ManageGroupDialog(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Checkbox(checked = isSelected, onCheckedChange = null)
|
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 = "删除选中"
|
text = "删除选中"
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
dismissButton = { TextButton(onClick = onDismiss) { Text("关闭") } }
|
dismissButton = { TextButton(onClick = onDismiss) { AppText("关闭") } }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ fun QuickInputBar(
|
|||||||
symbols.forEach { symbol ->
|
symbols.forEach { symbol ->
|
||||||
AssistChip(
|
AssistChip(
|
||||||
onClick = { onInsert(symbol) },
|
onClick = { onInsert(symbol) },
|
||||||
label = { Text(symbol) },
|
label = { AppText(symbol) },
|
||||||
modifier = Modifier.padding(end = 8.dp)
|
modifier = Modifier.padding(end = 8.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import androidx.compose.material.icons.filled.Group
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
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.divider.PillDivider
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.rules.RuleListScaffold
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -133,7 +133,7 @@ fun RssFavoritesScreen(
|
|||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(Icons.Default.Group, null, modifier = Modifier.size(18.dp))
|
Icon(Icons.Default.Group, null, modifier = Modifier.size(18.dp))
|
||||||
Spacer(Modifier.width(12.dp))
|
Spacer(Modifier.width(12.dp))
|
||||||
Text(stringResource(R.string.all))
|
AppText(stringResource(R.string.all))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -151,7 +151,7 @@ fun RssFavoritesScreen(
|
|||||||
modifier = Modifier.size(18.dp)
|
modifier = Modifier.size(18.dp)
|
||||||
)
|
)
|
||||||
Spacer(Modifier.width(12.dp))
|
Spacer(Modifier.width(12.dp))
|
||||||
Text(group)
|
AppText(group)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -166,7 +166,7 @@ fun RssFavoritesScreen(
|
|||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(Icons.Default.DeleteSweep, null, modifier = Modifier.size(18.dp))
|
Icon(Icons.Default.DeleteSweep, null, modifier = Modifier.size(18.dp))
|
||||||
Spacer(Modifier.width(12.dp))
|
Spacer(Modifier.width(12.dp))
|
||||||
Text(stringResource(R.string.delete_select_group))
|
AppText(stringResource(R.string.delete_select_group))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -179,7 +179,7 @@ fun RssFavoritesScreen(
|
|||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(Icons.Default.DeleteForever, null, modifier = Modifier.size(18.dp))
|
Icon(Icons.Default.DeleteForever, null, modifier = Modifier.size(18.dp))
|
||||||
Spacer(Modifier.width(12.dp))
|
Spacer(Modifier.width(12.dp))
|
||||||
Text(stringResource(R.string.all))
|
AppText(stringResource(R.string.all))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -248,14 +248,14 @@ fun RssFavoritesScreen(
|
|||||||
},
|
},
|
||||||
dropdownContent = { dismiss ->
|
dropdownContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.change_group)) },
|
text = { AppText(stringResource(R.string.change_group)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showSetGroupDialog = rssStar
|
showSetGroupDialog = rssStar
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.delete)) },
|
text = { AppText(stringResource(R.string.delete)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.deleteStar(rssStar)
|
viewModel.deleteStar(rssStar)
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|||||||
@@ -17,11 +17,9 @@ import androidx.compose.material.icons.filled.Delete
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -43,6 +41,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseRuleEvent
|
import io.legado.app.base.BaseRuleEvent
|
||||||
import io.legado.app.data.entities.RssSource
|
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.ActionItem
|
||||||
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
||||||
import io.legado.app.ui.widget.components.GroupManageBottomSheet
|
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.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
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.rules.RuleListScaffold
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
|
|
||||||
@@ -209,8 +209,12 @@ fun RssSourceScreen(
|
|||||||
onConfirm = { viewModel.saveImportedRules() },
|
onConfirm = { viewModel.saveImportedRules() },
|
||||||
itemContent = { source, _ ->
|
itemContent = { source, _ ->
|
||||||
Column {
|
Column {
|
||||||
Text(source.sourceName, style = MaterialTheme.typography.titleMedium)
|
AppText(source.sourceName, style = LegadoTheme.typography.titleMedium)
|
||||||
Text(source.sourceUrl, style = MaterialTheme.typography.bodySmall, maxLines = 1)
|
AppText(
|
||||||
|
source.sourceUrl,
|
||||||
|
style = LegadoTheme.typography.bodySmall,
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -225,16 +229,16 @@ fun RssSourceScreen(
|
|||||||
showDeleteRuleDialog?.let { source ->
|
showDeleteRuleDialog?.let { source ->
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteRuleDialog = null },
|
onDismissRequest = { showDeleteRuleDialog = null },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.del_msg)) },
|
text = { AppText(stringResource(R.string.del_msg)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(onClick = {
|
OutlinedButton(onClick = {
|
||||||
viewModel.del(source); showDeleteRuleDialog = null
|
viewModel.del(source); showDeleteRuleDialog = null
|
||||||
}) { Text(stringResource(R.string.ok)) }
|
}) { AppText(stringResource(R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
TextButton(onClick = { showDeleteRuleDialog = null }) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -287,11 +291,11 @@ fun RssSourceScreen(
|
|||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
onClick = { showGroupManageSheet = true },
|
onClick = { showGroupManageSheet = true },
|
||||||
text = { Text("分组管理") },
|
text = { AppText("分组管理") },
|
||||||
)
|
)
|
||||||
Box {
|
Box {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_rss_source)) },
|
text = { AppText(stringResource(R.string.import_rss_source)) },
|
||||||
onClick = { showImportMenu = true }
|
onClick = { showImportMenu = true }
|
||||||
)
|
)
|
||||||
RoundDropdownMenu(
|
RoundDropdownMenu(
|
||||||
@@ -299,7 +303,7 @@ fun RssSourceScreen(
|
|||||||
onDismissRequest = { showImportMenu = false }
|
onDismissRequest = { showImportMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_on_line)) },
|
text = { AppText(stringResource(R.string.import_on_line)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showImportMenu = false
|
showImportMenu = false
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -307,7 +311,7 @@ fun RssSourceScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_local)) },
|
text = { AppText(stringResource(R.string.import_local)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showImportMenu = false
|
showImportMenu = false
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -315,7 +319,7 @@ fun RssSourceScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.import_default_rule)) },
|
text = { AppText(stringResource(R.string.import_default_rule)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
showImportMenu = false
|
showImportMenu = false
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -326,29 +330,29 @@ fun RssSourceScreen(
|
|||||||
}
|
}
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.all)) },
|
text = { AppText(stringResource(R.string.all)) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter(null) }
|
onClick = { dismiss(); viewModel.setGroupFilter(null) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.enabled)) },
|
text = { AppText(stringResource(R.string.enabled)) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_ENABLED) }
|
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_ENABLED) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.disabled)) },
|
text = { AppText(stringResource(R.string.disabled)) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_DISABLED) }
|
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_DISABLED) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.need_login)) },
|
text = { AppText(stringResource(R.string.need_login)) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_LOGIN) }
|
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_LOGIN) }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.no_group)) },
|
text = { AppText(stringResource(R.string.no_group)) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_NO_GROUP) }
|
onClick = { dismiss(); viewModel.setGroupFilter(RssSourceViewModel.FILTER_NO_GROUP) }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
groups.forEach { group ->
|
groups.forEach { group ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(group) },
|
text = { AppText(group) },
|
||||||
onClick = { dismiss(); viewModel.setGroupFilter("${RssSourceViewModel.PREFIX_GROUP}$group") }
|
onClick = { dismiss(); viewModel.setGroupFilter("${RssSourceViewModel.PREFIX_GROUP}$group") }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
|||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TooltipAnchorPosition
|
import androidx.compose.material3.TooltipAnchorPosition
|
||||||
import androidx.compose.material3.TooltipBox
|
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.ImportBookSourceDialog
|
||||||
import io.legado.app.ui.association.ImportReplaceRuleDialog
|
import io.legado.app.ui.association.ImportReplaceRuleDialog
|
||||||
import io.legado.app.ui.association.ImportRssSourceDialog
|
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.EmptyMessageView
|
||||||
import io.legado.app.ui.widget.components.card.SelectionItemCard
|
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.CheckboxGroupContainer
|
||||||
import io.legado.app.ui.widget.components.checkBox.CheckboxItem
|
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.menuItem.RoundDropdownMenuItem
|
||||||
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
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.showDialogFragment
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ fun RuleSubScreen(
|
|||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(Icons.AutoMirrored.Filled.Sort, null, modifier = Modifier.size(18.dp))
|
Icon(Icons.AutoMirrored.Filled.Sort, null, modifier = Modifier.size(18.dp))
|
||||||
Spacer(Modifier.size(12.dp))
|
Spacer(Modifier.size(12.dp))
|
||||||
Text(stringResource(R.string.sort))
|
AppText(stringResource(R.string.sort))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -106,7 +106,7 @@ fun RuleSubScreen(
|
|||||||
TooltipBox(
|
TooltipBox(
|
||||||
positionProvider =
|
positionProvider =
|
||||||
TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
|
TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
|
||||||
tooltip = { PlainTooltip { Text("Localized description") } },
|
tooltip = { PlainTooltip { AppText("Localized description") } },
|
||||||
state = rememberTooltipState(),
|
state = rememberTooltipState(),
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
@@ -185,7 +185,7 @@ fun RuleSubScreen(
|
|||||||
},
|
},
|
||||||
dropdownContent = { dismiss ->
|
dropdownContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.delete)) },
|
text = { AppText(stringResource(R.string.delete)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.delete(ruleSub)
|
viewModel.delete(ruleSub)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -226,24 +226,24 @@ fun RuleSubEditDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text(stringResource(R.string.rule_subscription)) },
|
title = { AppText(stringResource(R.string.rule_subscription)) },
|
||||||
text = {
|
text = {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = name,
|
value = name,
|
||||||
onValueChange = { name = it },
|
onValueChange = { name = it },
|
||||||
label = { Text(stringResource(R.string.name)) },
|
label = { AppText(stringResource(R.string.name)) },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = url,
|
value = url,
|
||||||
onValueChange = { url = it },
|
onValueChange = { url = it },
|
||||||
label = { Text("URL") },
|
label = { AppText("URL") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = "订阅类型",
|
text = "订阅类型",
|
||||||
style = MaterialTheme.typography.titleSmall,
|
style = LegadoTheme.typography.titleSmall,
|
||||||
modifier = Modifier.padding(top = 8.dp)
|
modifier = Modifier.padding(top = 8.dp)
|
||||||
)
|
)
|
||||||
CheckboxGroupContainer(columns = 2) {
|
CheckboxGroupContainer(columns = 2) {
|
||||||
@@ -265,12 +265,12 @@ fun RuleSubEditDialog(
|
|||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
onConfirm(ruleSub.copy(name = name, url = url, type = type))
|
onConfirm(ruleSub.copy(name = name, url = url, type = type))
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismiss) {
|
TextButton(onClick = onDismiss) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -7,9 +7,13 @@ import androidx.compose.material3.MotionScheme
|
|||||||
import androidx.compose.material3.Shapes
|
import androidx.compose.material3.Shapes
|
||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
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)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -20,29 +24,82 @@ fun AppTheme(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val appThemeMode = ThemeResolver.resolveThemeMode(ThemeConfig.appTheme)
|
val appThemeMode = ThemeResolver.resolveThemeMode(ThemeConfig.appTheme)
|
||||||
val isPureBlack = ThemeConfig.isPureBlack
|
val isPureBlack = ThemeConfig.isPureBlack
|
||||||
val paletteStyle = ThemeConfig.paletteStyle
|
val paletteStyleStr = ThemeConfig.paletteStyle
|
||||||
val materialVersion = ThemeConfig.materialVersion
|
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 =
|
val colorScheme =
|
||||||
remember(context, appThemeMode, darkTheme, isPureBlack, paletteStyle, materialVersion) {
|
remember(context, appThemeMode, darkTheme, isPureBlack, paletteStyleStr, materialVersion) {
|
||||||
ThemeManager.getColorScheme(
|
ThemeManager.getColorScheme(
|
||||||
context = context,
|
context = context,
|
||||||
mode = appThemeMode,
|
mode = appThemeMode,
|
||||||
darkTheme = darkTheme,
|
darkTheme = darkTheme,
|
||||||
isAmoled = isPureBlack,
|
isAmoled = isPureBlack,
|
||||||
paletteStyle = paletteStyle,
|
paletteStyle = paletteStyleStr,
|
||||||
materialVersion = materialVersion
|
materialVersion = materialVersion
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialExpressiveTheme(
|
val themeColors = remember(colorScheme, darkTheme, seedColor, paletteStyle, colorSchemeMode) {
|
||||||
colorScheme = colorScheme,
|
LegadoThemeColors(
|
||||||
typography = Typography(),
|
colorScheme = colorScheme,
|
||||||
motionScheme = MotionScheme.expressive(),
|
isDark = darkTheme,
|
||||||
shapes = Shapes()
|
seedColor = seedColor,
|
||||||
|
paletteStyle = paletteStyle,
|
||||||
|
themeMode = colorSchemeMode,
|
||||||
|
useDynamicColor = appThemeMode == AppThemeMode.Dynamic,
|
||||||
|
composeEngine = composeEngine
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalLegadoThemeColors provides themeColors
|
||||||
) {
|
) {
|
||||||
AppBackground(darkTheme = darkTheme) {
|
when {
|
||||||
content()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,8 @@ import dev.chrisbanes.haze.HazeState
|
|||||||
import dev.chrisbanes.haze.hazeEffect
|
import dev.chrisbanes.haze.hazeEffect
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
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.config.themeConfig.ThemeConfig
|
||||||
|
import io.legado.app.ui.theme.hazeStyle.HazeLegado
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动感知全局配置的 HazeSource
|
* 自动感知全局配置的 HazeSource
|
||||||
@@ -31,9 +31,9 @@ fun Modifier.responsiveHazeEffect(
|
|||||||
if (!enableBlur) return this
|
if (!enableBlur) return this
|
||||||
|
|
||||||
val style = if (enableProgressiveBlur) {
|
val style = if (enableProgressiveBlur) {
|
||||||
HazeMaterials.ultraThin()
|
HazeLegado.ultraThin()
|
||||||
} else {
|
} else {
|
||||||
HazeMaterials.regular()
|
HazeLegado.regular()
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.hazeEffect(
|
return this.hazeEffect(
|
||||||
@@ -61,6 +61,6 @@ fun Modifier.regularHazeEffect(state: HazeState): Modifier {
|
|||||||
|
|
||||||
return this.hazeEffect(
|
return this.hazeEffect(
|
||||||
state = state,
|
state = state,
|
||||||
style = HazeMaterials.ultraThin()
|
style = HazeLegado.ultraThin()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<HazeState?> { 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
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.materialkolor.Contrast
|
|||||||
import com.materialkolor.PaletteStyle
|
import com.materialkolor.PaletteStyle
|
||||||
import com.materialkolor.dynamiccolor.ColorSpec
|
import com.materialkolor.dynamiccolor.ColorSpec
|
||||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
import top.yukonga.miuix.kmp.theme.ColorSchemeMode
|
||||||
|
|
||||||
object ThemeResolver {
|
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 {
|
fun resolveColorSpecVersion(colorSpec: ThemeColorSpec): ColorSpec.SpecVersion {
|
||||||
return when (colorSpec) {
|
return when (colorSpec) {
|
||||||
ThemeColorSpec.SPEC_2025 -> ColorSpec.SpecVersion.SPEC_2025
|
ThemeColorSpec.SPEC_2025 -> ColorSpec.SpecVersion.SPEC_2025
|
||||||
|
|||||||
@@ -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)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -13,7 +13,6 @@ import androidx.compose.material3.CardDefaults
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
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.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -54,9 +55,9 @@ fun CollapsibleHeader(
|
|||||||
if (titleContent != null) {
|
if (titleContent != null) {
|
||||||
titleContent()
|
titleContent()
|
||||||
} else {
|
} else {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodySmallEmphasized.copy(
|
style = LegadoTheme.typography.bodySmallEmphasized.copy(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
),
|
),
|
||||||
@@ -64,9 +65,9 @@ fun CollapsibleHeader(
|
|||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
subtitle?.let {
|
subtitle?.let {
|
||||||
Text(
|
AppText(
|
||||||
text = it,
|
text = it,
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized.copy(
|
style = LegadoTheme.typography.labelSmallEmphasized.copy(
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
),
|
),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import androidx.compose.animation.togetherWith
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.TextDecoration
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AnimatedText(
|
fun AnimatedText(
|
||||||
@@ -60,7 +60,7 @@ fun AnimatedText(
|
|||||||
},
|
},
|
||||||
label = ""
|
label = ""
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
style = style,
|
style = style,
|
||||||
color = color,
|
color = color,
|
||||||
softWrap = softWrap,
|
softWrap = softWrap,
|
||||||
@@ -117,7 +117,7 @@ fun AnimatedTextLine(
|
|||||||
label = "LineAnimation",
|
label = "LineAnimation",
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) { targetText ->
|
) { targetText ->
|
||||||
Text(
|
AppText(
|
||||||
text = targetText,
|
text = targetText,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
style = style,
|
style = style,
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package io.legado.app.ui.widget.components
|
|||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.RowScope
|
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
@@ -11,29 +10,27 @@ import androidx.compose.material3.FabPosition
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.ScaffoldDefaults
|
import androidx.compose.material3.ScaffoldDefaults
|
||||||
import androidx.compose.material3.TopAppBarColors
|
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
|
||||||
import androidx.compose.material3.contentColorFor
|
import androidx.compose.material3.contentColorFor
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
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 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)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AppScaffold(
|
fun AppScaffold(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
title: (@Composable () -> Unit)? = null,
|
topBar: @Composable (HazeState) -> Unit = {},
|
||||||
subtitle: (@Composable () -> Unit)? = null,
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
|
||||||
navigationIcon: @Composable () -> Unit = {},
|
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
|
||||||
colors: TopAppBarColors = GlassTopAppBarDefaults.glassColors(),
|
|
||||||
topBar: @Composable () -> Unit = {},
|
|
||||||
bottomBar: @Composable () -> Unit = {},
|
bottomBar: @Composable () -> Unit = {},
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
floatingActionButton: @Composable () -> Unit = {},
|
floatingActionButton: @Composable () -> Unit = {},
|
||||||
@@ -45,47 +42,73 @@ fun AppScaffold(
|
|||||||
val isDark = isSystemInDarkTheme()
|
val isDark = isSystemInDarkTheme()
|
||||||
val hasImageBg = ThemeConfig.hasImageBg(isDark)
|
val hasImageBg = ThemeConfig.hasImageBg(isDark)
|
||||||
val hazeState = remember { HazeState() }
|
val hazeState = remember { HazeState() }
|
||||||
|
val composeEngine = LegadoTheme.composeEngine
|
||||||
|
|
||||||
val containerColor = if (hasImageBg) {
|
val containerColor = if (hasImageBg) {
|
||||||
Color.Transparent
|
Color.Transparent
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.background
|
LegadoTheme.colorScheme.background
|
||||||
}
|
}
|
||||||
|
|
||||||
val finalTopBar = @Composable {
|
val miuixContainerColor = if (hasImageBg) {
|
||||||
Box(modifier = Modifier.responsiveHazeEffect(state = hazeState)) {
|
Color.Transparent
|
||||||
if (title != null) {
|
} else {
|
||||||
GlassMediumFlexibleTopAppBar(
|
MiuixTheme.colorScheme.surface
|
||||||
title = title,
|
}
|
||||||
subtitle = subtitle,
|
|
||||||
scrollBehavior = scrollBehavior,
|
CompositionLocalProvider(LocalHazeState provides hazeState) {
|
||||||
navigationIcon = navigationIcon,
|
when {
|
||||||
actions = actions,
|
ThemeResolver.isMiuixEngine(composeEngine) -> {
|
||||||
colors = colors
|
val miuixFabPosition = when (floatingActionButtonPosition) {
|
||||||
)
|
FabPosition.End -> MiuixFabPosition.End
|
||||||
} else {
|
FabPosition.Center -> MiuixFabPosition.Center
|
||||||
topBar()
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.widthIn
|
|||||||
import androidx.compose.foundation.layout.wrapContentSize
|
import androidx.compose.foundation.layout.wrapContentSize
|
||||||
import androidx.compose.material3.ContainedLoadingIndicator
|
import androidx.compose.material3.ContainedLoadingIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.TextUnit
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -70,7 +70,7 @@ fun EmptyMessageView(
|
|||||||
|
|
||||||
AnimatedTextLine(
|
AnimatedTextLine(
|
||||||
text = message,
|
text = message,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = LegadoTheme.typography.labelLarge,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
softWrap = true,
|
softWrap = true,
|
||||||
|
|||||||
@@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -31,9 +30,11 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.button.SmallTextButton
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
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.settingItem.SettingItem
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -52,10 +53,10 @@ fun GroupManageBottomSheet(
|
|||||||
.padding(bottom = 16.dp),
|
.padding(bottom = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
modifier = Modifier.padding(bottom = 16.dp),
|
modifier = Modifier.padding(bottom = 16.dp),
|
||||||
text = stringResource(R.string.group_manage),
|
text = stringResource(R.string.group_manage),
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = LegadoTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
items(groups, key = { it }) { group ->
|
items(groups, key = { it }) { group ->
|
||||||
@@ -115,7 +116,7 @@ private fun GroupItem(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.heightIn(min = 48.dp),
|
.heightIn(min = 48.dp),
|
||||||
label = { Text(stringResource(R.string.edit)) },
|
label = { AppText(stringResource(R.string.edit)) },
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = 4.dp,
|
top = 4.dp,
|
||||||
bottom = 4.dp,
|
bottom = 4.dp,
|
||||||
|
|||||||
@@ -10,6 +10,40 @@ import androidx.compose.material3.SwitchDefaults
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
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
|
@Composable
|
||||||
fun IconSwitch(
|
fun IconSwitch(
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -43,6 +42,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
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.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ fun SearchBarSection(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.heightIn(min = 48.dp)
|
.heightIn(min = 48.dp)
|
||||||
.padding(horizontal = 4.dp),
|
.padding(horizontal = 4.dp),
|
||||||
placeholder = { Text(placeholder) },
|
placeholder = { AppText(placeholder) },
|
||||||
leadingIcon = leadingIcon,
|
leadingIcon = leadingIcon,
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import androidx.compose.material3.HorizontalFloatingToolbar
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TooltipAnchorPosition
|
import androidx.compose.material3.TooltipAnchorPosition
|
||||||
import androidx.compose.material3.TooltipBox
|
import androidx.compose.material3.TooltipBox
|
||||||
import androidx.compose.material3.TooltipDefaults
|
import androidx.compose.material3.TooltipDefaults
|
||||||
@@ -27,6 +26,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
data class SelectionActions(
|
data class SelectionActions(
|
||||||
val primaryAction: ActionItem,
|
val primaryAction: ActionItem,
|
||||||
@@ -84,7 +84,7 @@ fun SelectionBottomBar(
|
|||||||
) {
|
) {
|
||||||
secondaryActions.forEach { action ->
|
secondaryActions.forEach { action ->
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(action.text) },
|
text = { AppText(action.text) },
|
||||||
leadingIcon = action.icon,
|
leadingIcon = action.icon,
|
||||||
onClick = {
|
onClick = {
|
||||||
action.onClick()
|
action.onClick()
|
||||||
@@ -101,7 +101,7 @@ fun SelectionBottomBar(
|
|||||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
||||||
TooltipAnchorPosition.Above
|
TooltipAnchorPosition.Above
|
||||||
),
|
),
|
||||||
tooltip = { PlainTooltip { Text(primaryAction.text) } },
|
tooltip = { PlainTooltip { AppText(primaryAction.text) } },
|
||||||
state = rememberTooltipState(),
|
state = rememberTooltipState(),
|
||||||
) {
|
) {
|
||||||
FilledIconButton(
|
FilledIconButton(
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import androidx.compose.foundation.layout.ColumnScope
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
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.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.unit.dp
|
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
|
* Settings Group Container by https://github.com/wxxsfxyzm/InstallerX-Revived
|
||||||
@@ -29,24 +29,33 @@ fun SplicedColumnGroup(
|
|||||||
title: String = "",
|
title: String = "",
|
||||||
content: @Composable ColumnScope.() -> Unit,
|
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()) {
|
if (title.isNotEmpty()) {
|
||||||
Text(
|
AdaptiveTitle(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp)
|
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Card(
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
shape = RoundedCornerShape(16.dp),
|
MiuixCard {
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.Transparent),
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.animateContentSize()
|
.animateContentSize()
|
||||||
) {
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
Column(
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.animateContentSize()
|
||||||
|
.clip(RoundedCornerShape(16.dp)),
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp)
|
verticalArrangement = Arrangement.spacedBy(2.dp)
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
|
|||||||
+12
-11
@@ -15,7 +15,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -26,7 +25,9 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.data.entities.Bookmark
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -50,16 +51,16 @@ fun BookmarkEditSheet(
|
|||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = bookmark.chapterName,
|
text = bookmark.chapterName,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = bookText,
|
value = bookText,
|
||||||
onValueChange = { bookText = it },
|
onValueChange = { bookText = it },
|
||||||
label = { Text("原文") },
|
label = { AppText("原文") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
maxLines = 10
|
maxLines = 10
|
||||||
)
|
)
|
||||||
@@ -69,7 +70,7 @@ fun BookmarkEditSheet(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = content,
|
value = content,
|
||||||
onValueChange = { content = it },
|
onValueChange = { content = it },
|
||||||
label = { Text("摘要/笔记") },
|
label = { AppText("摘要/笔记") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
maxLines = 5
|
maxLines = 5
|
||||||
)
|
)
|
||||||
@@ -86,7 +87,7 @@ fun BookmarkEditSheet(
|
|||||||
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
|
colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
Text("删除")
|
AppText("删除")
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
@@ -99,7 +100,7 @@ fun BookmarkEditSheet(
|
|||||||
},
|
},
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
Text("保存")
|
AppText("保存")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
@@ -109,8 +110,8 @@ fun BookmarkEditSheet(
|
|||||||
if (showDeleteConfirmDialog) {
|
if (showDeleteConfirmDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteConfirmDialog = false },
|
onDismissRequest = { showDeleteConfirmDialog = false },
|
||||||
title = { Text("确认删除") },
|
title = { AppText("确认删除") },
|
||||||
text = { Text("你确定要删除这条书签吗?") },
|
text = { AppText("你确定要删除这条书签吗?") },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -119,14 +120,14 @@ fun BookmarkEditSheet(
|
|||||||
},
|
},
|
||||||
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error)
|
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error)
|
||||||
) {
|
) {
|
||||||
Text("删除")
|
AppText("删除")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = { showDeleteConfirmDialog = false }
|
onClick = { showDeleteConfirmDialog = false }
|
||||||
) {
|
) {
|
||||||
Text("取消")
|
AppText("取消")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
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.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.data.entities.Bookmark
|
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)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -49,17 +50,17 @@ fun BookmarkItem(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = bookmark.chapterName,
|
text = bookmark.chapterName,
|
||||||
style = MaterialTheme.typography.titleSmallEmphasized,
|
style = LegadoTheme.typography.titleSmallEmphasized,
|
||||||
color = if (isDur) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary
|
color = if (isDur) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary
|
||||||
)
|
)
|
||||||
|
|
||||||
if (bookmark.bookText.isNotEmpty()) {
|
if (bookmark.bookText.isNotEmpty()) {
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = bookmark.bookText,
|
text = bookmark.bookText,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
@@ -68,9 +69,9 @@ fun BookmarkItem(
|
|||||||
|
|
||||||
if (bookmark.content.isNotEmpty()) {
|
if (bookmark.content.isNotEmpty()) {
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = bookmark.content,
|
text = bookmark.content,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package io.legado.app.ui.widget.components.button
|
|||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AlertButton(
|
fun AlertButton(
|
||||||
@@ -24,6 +24,6 @@ fun AlertButton(
|
|||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text(text = text)
|
AppText(text = text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,8 +8,6 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.ToggleButton
|
import androidx.compose.material3.ToggleButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -21,6 +19,8 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
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
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@@ -73,9 +73,9 @@ fun AnimatedActionButton(
|
|||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = showText
|
visible = showText
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = if (lastCheckedState) activeText else inactiveText,
|
text = if (lastCheckedState) activeText else inactiveText,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
softWrap = false
|
softWrap = false
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.animation.togetherWith
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.material3.ContainedLoadingIndicator
|
import androidx.compose.material3.ContainedLoadingIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -38,7 +38,7 @@ fun AnimatedTextButton(
|
|||||||
if (loading) {
|
if (loading) {
|
||||||
ContainedLoadingIndicator()
|
ContainedLoadingIndicator()
|
||||||
} else {
|
} else {
|
||||||
Text(text)
|
AppText(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,11 +15,9 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.IconToggleButtonShapes
|
import androidx.compose.material3.IconToggleButtonShapes
|
||||||
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
|
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedIconButton
|
import androidx.compose.material3.OutlinedIconButton
|
||||||
import androidx.compose.material3.OutlinedIconToggleButton
|
import androidx.compose.material3.OutlinedIconToggleButton
|
||||||
import androidx.compose.material3.OutlinedToggleButton
|
import androidx.compose.material3.OutlinedToggleButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -31,7 +29,13 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
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 kotlinx.coroutines.delay
|
||||||
|
import top.yukonga.miuix.kmp.basic.Icon as MiuixIcon
|
||||||
|
import top.yukonga.miuix.kmp.basic.IconButton as MiuixIconButton
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@@ -41,22 +45,33 @@ fun SmallIconButton(
|
|||||||
icon: ImageVector,
|
icon: ImageVector,
|
||||||
contentDescription: String? = null
|
contentDescription: String? = null
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) {
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
IconButton(
|
MiuixIconButton(
|
||||||
onClick = onClick,
|
onClick = onClick
|
||||||
modifier = Modifier.size(
|
|
||||||
IconButtonDefaults.extraSmallContainerSize(
|
|
||||||
IconButtonDefaults.IconButtonWidthOption.Uniform
|
|
||||||
)
|
|
||||||
),
|
|
||||||
shape = IconButtonDefaults.extraSmallRoundShape,
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
MiuixIcon(
|
||||||
imageVector = icon,
|
imageVector = icon,
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription
|
||||||
modifier = Modifier.size(IconButtonDefaults.extraSmallIconSize),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} 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(
|
AnimatedVisibility(
|
||||||
visible = showText
|
visible = showText
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = if (lastCheckedState) activeText else inactiveText,
|
text = if (lastCheckedState) activeText else inactiveText,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
modifier = Modifier.padding(start = 6.dp),
|
modifier = Modifier.padding(start = 6.dp),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
softWrap = false
|
softWrap = false
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
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
|
@Composable
|
||||||
fun SmallTextButton(
|
fun SmallTextButton(
|
||||||
@@ -32,9 +33,9 @@ fun SmallTextButton(
|
|||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
Spacer(Modifier.width(4.dp))
|
Spacer(Modifier.width(4.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.labelMedium
|
style = LegadoTheme.typography.labelMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,6 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedIconButton
|
import androidx.compose.material3.OutlinedIconButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.ToggleButton
|
import androidx.compose.material3.ToggleButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
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.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
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
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
enum class TopBarButtonVariant {
|
enum class TopBarButtonVariant {
|
||||||
@@ -109,13 +111,22 @@ fun TopbarNavigationButton(
|
|||||||
contentDescription: String? = "返回",
|
contentDescription: String? = "返回",
|
||||||
style: TopBarButtonVariant = TopBarButtonVariant.Filled
|
style: TopBarButtonVariant = TopBarButtonVariant.Filled
|
||||||
) {
|
) {
|
||||||
TopBarButton(
|
if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) {
|
||||||
onClick = onClick,
|
MiuixButton(
|
||||||
imageVector = imageVector,
|
onClick = onClick,
|
||||||
contentDescription = contentDescription,
|
imageVector = imageVector,
|
||||||
modifier = modifier.padding(horizontal = 12.dp),
|
contentDescription = contentDescription,
|
||||||
style = style
|
modifier = modifier.padding(horizontal = 16.dp)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
TopBarButton(
|
||||||
|
onClick = onClick,
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = modifier.padding(horizontal = 12.dp),
|
||||||
|
style = style
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -126,21 +137,29 @@ fun TopBarActionButton(
|
|||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val enableProgressive = ThemeConfig.enableProgressiveBlur
|
val enableProgressive = ThemeConfig.enableProgressiveBlur
|
||||||
|
if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) {
|
||||||
if (enableProgressive) {
|
MiuixButton(
|
||||||
TopBarButton(
|
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
imageVector = imageVector,
|
imageVector = imageVector,
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription,
|
||||||
modifier = modifier.padding(end = 12.dp),
|
modifier = modifier.padding(end = 8.dp),
|
||||||
style = TopBarButtonVariant.Filled
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
IconButton(onClick = onClick) {
|
if (enableProgressive) {
|
||||||
Icon(
|
TopBarButton(
|
||||||
|
onClick = onClick,
|
||||||
imageVector = imageVector,
|
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
|
showText = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) {
|
||||||
ToggleButton(
|
MiuixToggleButton(
|
||||||
modifier = modifier.height(36.dp),
|
checked = checked,
|
||||||
contentPadding = PaddingValues(horizontal = 8.dp),
|
onCheckedChange = onCheckedChange,
|
||||||
checked = checked,
|
iconChecked = iconChecked,
|
||||||
onCheckedChange = {
|
iconUnchecked = iconUnchecked
|
||||||
lastCheckedState = it
|
)
|
||||||
onCheckedChange(it)
|
} else {
|
||||||
showText = true
|
ToggleButton(
|
||||||
}
|
modifier = modifier.height(36.dp),
|
||||||
) {
|
contentPadding = PaddingValues(horizontal = 8.dp),
|
||||||
Row(
|
checked = checked,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
onCheckedChange = {
|
||||||
horizontalArrangement = Arrangement.Center
|
lastCheckedState = it
|
||||||
) {
|
onCheckedChange(it)
|
||||||
|
showText = true
|
||||||
AnimatedContent(
|
|
||||||
targetState = checked,
|
|
||||||
label = "IconAnimation"
|
|
||||||
) { targetChecked ->
|
|
||||||
AnimatedIcon(
|
|
||||||
modifier = Modifier.size(20.dp),
|
|
||||||
imageVector = if (targetChecked) iconChecked else iconUnchecked,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
) {
|
||||||
AnimatedVisibility(
|
Row(
|
||||||
visible = showText
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
|
||||||
text = if (lastCheckedState) activeText else inactiveText,
|
AnimatedContent(
|
||||||
style = MaterialTheme.typography.labelMedium,
|
targetState = checked,
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
label = "IconAnimation"
|
||||||
maxLines = 1,
|
) { targetChecked ->
|
||||||
softWrap = false
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,79 @@ import androidx.compose.foundation.BorderStroke
|
|||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardColors
|
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.CardElevation
|
import androidx.compose.material3.CardElevation
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.Shape
|
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.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)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -19,43 +84,50 @@ fun GlassCard(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
shape: Shape = CardDefaults.shape,
|
shape: Shape = CardDefaults.shape,
|
||||||
colors: CardColors? = null,
|
cornerRadius: Dp = MiuixCardDefaults.CornerRadius,
|
||||||
|
containerColor: Color? = null,
|
||||||
|
contentColor: Color? = null,
|
||||||
elevation: CardElevation = CardDefaults.cardElevation(),
|
elevation: CardElevation = CardDefaults.cardElevation(),
|
||||||
border: BorderStroke? = null,
|
border: BorderStroke? = null,
|
||||||
content: @Composable ColumnScope.() -> Unit
|
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(
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
@Composable
|
||||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ import androidx.compose.material3.Checkbox
|
|||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.ListItemDefaults
|
import androidx.compose.material3.ListItemDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
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.button.SmallIconButton
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
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.ReorderableItem
|
||||||
import sh.calvin.reorderable.ReorderableLazyListState
|
import sh.calvin.reorderable.ReorderableLazyListState
|
||||||
|
import top.yukonga.miuix.kmp.basic.BasicComponent
|
||||||
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SelectionItemCard(
|
fun SelectionItemCard(
|
||||||
@@ -66,11 +71,14 @@ fun SelectionItemCard(
|
|||||||
) {
|
) {
|
||||||
var showMenu by remember { mutableStateOf(false) }
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val composeEngine = ThemeResolver.isMiuixEngine(composeEngine)
|
||||||
val animatedContainerColor by animateColorAsState(
|
val animatedContainerColor by animateColorAsState(
|
||||||
targetValue = if (isSelected)
|
targetValue = if (isSelected)
|
||||||
selectedContainerColor ?: MaterialTheme.colorScheme.secondaryContainer
|
selectedContainerColor
|
||||||
|
?: if (composeEngine) MiuixTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.secondaryContainer
|
||||||
else
|
else
|
||||||
containerColor ?: MaterialTheme.colorScheme.surfaceContainerLow,
|
containerColor
|
||||||
|
?: if (composeEngine) MiuixTheme.colorScheme.surfaceContainer else MaterialTheme.colorScheme.surfaceContainerLow,
|
||||||
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
||||||
label = "CardColor"
|
label = "CardColor"
|
||||||
)
|
)
|
||||||
@@ -81,7 +89,7 @@ fun SelectionItemCard(
|
|||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.shapes.medium,
|
||||||
colors = CardDefaults.cardColors(containerColor = animatedContainerColor),
|
containerColor = animatedContainerColor,
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = elevation)
|
elevation = CardDefaults.cardElevation(defaultElevation = elevation)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@@ -113,28 +121,49 @@ fun SelectionItemCard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListItem(
|
if (composeEngine) {
|
||||||
modifier = Modifier.weight(1f),
|
BasicComponent(
|
||||||
headlineContent = {
|
modifier = Modifier.weight(1f)
|
||||||
Text(
|
) {
|
||||||
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.titleSmall,
|
style = LegadoTheme.typography.titleSmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
},
|
if (!subtitle.isNullOrBlank()) {
|
||||||
supportingContent = if (!subtitle.isNullOrBlank()) {
|
AppText(
|
||||||
{
|
|
||||||
Text(
|
|
||||||
text = subtitle,
|
text = subtitle,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
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(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
@@ -143,7 +172,7 @@ fun SelectionItemCard(
|
|||||||
.padding(end = 8.dp)
|
.padding(end = 8.dp)
|
||||||
) {
|
) {
|
||||||
onEnabledChange?.let {
|
onEnabledChange?.let {
|
||||||
Switch(
|
AdaptiveSwitch(
|
||||||
modifier = Modifier.scale(0.8f),
|
modifier = Modifier.scale(0.8f),
|
||||||
checked = isEnabled,
|
checked = isEnabled,
|
||||||
onCheckedChange = it
|
onCheckedChange = it
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,50 +6,42 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
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.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.text.TextStyle
|
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 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
|
import io.legado.app.ui.widget.components.AnimatedTextLine
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
fun PreviewTextCard() {
|
|
||||||
MaterialTheme {
|
|
||||||
TextCard(
|
|
||||||
text = "v1.0.0"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TextCard(
|
fun TextCard(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
text: String,
|
text: String,
|
||||||
icon: ImageVector? = null,
|
icon: ImageVector? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
backgroundColor: Color = colorScheme.primaryContainer,
|
backgroundColor: Color = MaterialTheme.colorScheme.primaryContainer,
|
||||||
contentColor: Color = colorScheme.onPrimaryContainer,
|
contentColor: Color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
cornerRadius: Dp = 8.dp,
|
cornerRadius: Dp = 8.dp,
|
||||||
horizontalPadding: Dp = 8.dp,
|
horizontalPadding: Dp = 8.dp,
|
||||||
verticalPadding: Dp = 2.dp,
|
verticalPadding: Dp = 2.dp,
|
||||||
iconSize: Dp = 14.dp,
|
iconSize: Dp = 14.dp,
|
||||||
spacing: Dp = 4.dp,
|
spacing: Dp = 4.dp,
|
||||||
textStyle: TextStyle = MaterialTheme.typography.labelSmall
|
textStyle: TextStyle = LegadoTheme.typography.labelSmallEmphasized
|
||||||
) {
|
) {
|
||||||
GlassCard(
|
NormalCard(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = RoundedCornerShape(cornerRadius),
|
shape = RoundedCornerShape(cornerRadius),
|
||||||
colors = CardDefaults.cardColors(containerColor = backgroundColor),
|
containerColor = backgroundColor,
|
||||||
|
contentColor = contentColor,
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
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
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CheckboxItem(
|
fun CheckboxItem(
|
||||||
@@ -45,9 +46,9 @@ fun CheckboxItem(
|
|||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
modifier = Modifier.alpha(alpha)
|
modifier = Modifier.alpha(alpha)
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = LegadoTheme.typography.bodyMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp)
|
.padding(start = 12.dp)
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.StrokeCap
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.unit.dp
|
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 io.legado.app.ui.widget.components.card.TextCard
|
||||||
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookshelfCover(
|
fun BookshelfCover(
|
||||||
@@ -27,6 +31,16 @@ fun BookshelfCover(
|
|||||||
sourceOrigin: String? = null,
|
sourceOrigin: String? = null,
|
||||||
onLoadFinish: (() -> Unit)? = 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) {
|
Box(modifier = modifier) {
|
||||||
BookCover(
|
BookCover(
|
||||||
name = name,
|
name = name,
|
||||||
@@ -44,8 +58,8 @@ fun BookshelfCover(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
.padding(2.dp),
|
.padding(2.dp),
|
||||||
backgroundColor = MaterialTheme.colorScheme.secondaryContainer,
|
backgroundColor = backgroundColor,
|
||||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
contentColor = contentColor,
|
||||||
cornerRadius = 4.dp,
|
cornerRadius = 4.dp,
|
||||||
horizontalPadding = 4.dp,
|
horizontalPadding = 4.dp,
|
||||||
verticalPadding = 0.dp
|
verticalPadding = 0.dp
|
||||||
@@ -59,8 +73,8 @@ fun BookshelfCover(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 4.dp, vertical = 6.dp)
|
.padding(horizontal = 4.dp, vertical = 6.dp)
|
||||||
.height(3.dp),
|
.height(3.dp),
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = LegadoTheme.colorScheme.primary,
|
||||||
trackColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f),
|
trackColor = LegadoTheme.colorScheme.primary.copy(alpha = 0.2f),
|
||||||
strokeCap = StrokeCap.Round
|
strokeCap = StrokeCap.Round
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
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.HsvColorPicker
|
||||||
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
|
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
|
||||||
import io.legado.app.R
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -86,9 +87,9 @@ fun ColorPickerSheet(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = "颜色选择",
|
text = "颜色选择",
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = LegadoTheme.typography.titleLarge,
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -168,9 +169,9 @@ fun ColorPickerSheet(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = "#${Integer.toHexString(currentColor.toArgb()).uppercase()}",
|
text = "#${Integer.toHexString(currentColor.toArgb()).uppercase()}",
|
||||||
style = MaterialTheme.typography.bodyLarge
|
style = LegadoTheme.typography.bodyLarge
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@@ -178,14 +179,14 @@ fun ColorPickerSheet(
|
|||||||
horizontalArrangement = Arrangement.End
|
horizontalArrangement = Arrangement.End
|
||||||
) {
|
) {
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextButton(onClick = onDismissRequest) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
onColorSelected(currentColor.toArgb())
|
onColorSelected(currentColor.toArgb())
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ import androidx.compose.foundation.lazy.LazyRow
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.AssistChip
|
import androidx.compose.material3.AssistChip
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -22,6 +20,8 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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
|
@Composable
|
||||||
fun TextListInputDialog(
|
fun TextListInputDialog(
|
||||||
@@ -36,22 +36,22 @@ fun TextListInputDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = { Text(title) },
|
title = { AppText(title) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = text,
|
value = text,
|
||||||
onValueChange = { text = it },
|
onValueChange = { text = it },
|
||||||
label = { Text(hint) },
|
label = { AppText(hint) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
|
|
||||||
if (suggestions.isNotEmpty()) {
|
if (suggestions.isNotEmpty()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = "建议:",
|
text = "建议:",
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
modifier = Modifier.padding(bottom = 4.dp)
|
modifier = Modifier.padding(bottom = 4.dp)
|
||||||
)
|
)
|
||||||
LazyRow(
|
LazyRow(
|
||||||
@@ -61,7 +61,7 @@ fun TextListInputDialog(
|
|||||||
items(suggestions) { suggestion ->
|
items(suggestions) { suggestion ->
|
||||||
AssistChip(
|
AssistChip(
|
||||||
onClick = { text = suggestion },
|
onClick = { text = suggestion },
|
||||||
label = { Text(suggestion) }
|
label = { AppText(suggestion) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,12 +72,12 @@ fun TextListInputDialog(
|
|||||||
TextButton(
|
TextButton(
|
||||||
onClick = { onConfirm(text) }
|
onClick = { onConfirm(text) }
|
||||||
) {
|
) {
|
||||||
Text(stringResource(android.R.string.ok))
|
AppText(stringResource(android.R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextButton(onClick = onDismissRequest) {
|
||||||
Text(stringResource(android.R.string.cancel))
|
AppText(stringResource(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
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
|
@Composable
|
||||||
fun PillHeaderDivider(
|
fun PillHeaderDivider(
|
||||||
@@ -40,9 +41,9 @@ fun PillHeaderDivider(
|
|||||||
.background(dotColor)
|
.background(dotColor)
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = LegadoTheme.typography.labelSmall,
|
||||||
color = titleColor,
|
color = titleColor,
|
||||||
modifier = Modifier.padding(horizontal = 12.dp),
|
modifier = Modifier.padding(horizontal = 12.dp),
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
enum class FilePickerSheetMode {
|
enum class FilePickerSheetMode {
|
||||||
DIR, FILE, EXPORT
|
DIR, FILE, EXPORT
|
||||||
@@ -56,9 +57,9 @@ fun FilePickerSheet(
|
|||||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = LegadoTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(bottom = 20.dp)
|
modifier = Modifier.padding(bottom = 20.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -141,9 +142,9 @@ private fun RowScope.FilePickerOptionCard(
|
|||||||
tint = MaterialTheme.colorScheme.primary
|
tint = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
AppText(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
maxLines = 1
|
maxLines = 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-9
@@ -25,7 +25,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedIconButton
|
import androidx.compose.material3.OutlinedIconButton
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
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.button.AnimatedActionButton
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +61,7 @@ fun HeatmapCalendarTopBar(
|
|||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Text("时间线", style = MaterialTheme.typography.titleMedium)
|
AppText("时间线", style = LegadoTheme.typography.titleMedium)
|
||||||
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
AnimatedActionButton(
|
AnimatedActionButton(
|
||||||
@@ -107,7 +108,7 @@ fun WeekdayLabelsColumn(
|
|||||||
|
|
||||||
labels.forEachIndexed { index, label ->
|
labels.forEachIndexed { index, label ->
|
||||||
if (index % 2 == 0) {
|
if (index % 2 == 0) {
|
||||||
Text(
|
AppText(
|
||||||
text = label,
|
text = label,
|
||||||
fontSize = 10.sp,
|
fontSize = 10.sp,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
@@ -170,7 +171,7 @@ fun NoEarlierDataIndicator(
|
|||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
"没有更早数据".forEach { char ->
|
"没有更早数据".forEach { char ->
|
||||||
Text(
|
AppText(
|
||||||
text = char.toString(),
|
text = char.toString(),
|
||||||
fontSize = 9.sp,
|
fontSize = 9.sp,
|
||||||
lineHeight = 12.sp,
|
lineHeight = 12.sp,
|
||||||
@@ -252,7 +253,7 @@ fun HeatmapWeekColumn(
|
|||||||
|
|
||||||
// 月份标签
|
// 月份标签
|
||||||
if (firstDayOfMonth != null) {
|
if (firstDayOfMonth != null) {
|
||||||
Text(
|
AppText(
|
||||||
text = "${firstDayOfMonth.monthValue}月",
|
text = "${firstDayOfMonth.monthValue}月",
|
||||||
fontSize = 10.sp,
|
fontSize = 10.sp,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
@@ -280,9 +281,9 @@ fun HeatmapLegend(
|
|||||||
) {
|
) {
|
||||||
val legendUnit = if (mode == HeatmapMode.COUNT) "次" else "长"
|
val legendUnit = if (mode == HeatmapMode.COUNT) "次" else "长"
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
"少($legendUnit)",
|
"少($legendUnit)",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = Color.Gray
|
color = Color.Gray
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -298,9 +299,9 @@ fun HeatmapLegend(
|
|||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
AppText(
|
||||||
"多($legendUnit)",
|
"多($legendUnit)",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = LegadoTheme.typography.bodySmall,
|
||||||
color = Color.Gray
|
color = Color.Gray
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-11
@@ -42,7 +42,6 @@ import androidx.compose.material3.OutlinedTextField
|
|||||||
import androidx.compose.material3.OutlinedToggleButton
|
import androidx.compose.material3.OutlinedToggleButton
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
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.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.AnimatedText
|
||||||
import io.legado.app.ui.widget.components.AppScaffold
|
import io.legado.app.ui.widget.components.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -77,25 +78,25 @@ fun SourceInputDialog(
|
|||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = { Text(title) },
|
title = { AppText(title) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = text,
|
value = text,
|
||||||
onValueChange = { text = it },
|
onValueChange = { text = it },
|
||||||
label = { Text(hint) },
|
label = { AppText(hint) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
maxLines = 5
|
maxLines = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
if (historyValues.isNotEmpty()) {
|
if (historyValues.isNotEmpty()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text("历史记录:", style = MaterialTheme.typography.labelSmall)
|
AppText("历史记录:", style = LegadoTheme.typography.labelSmall)
|
||||||
LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
items(historyValues) { history ->
|
items(historyValues) { history ->
|
||||||
AssistChip(
|
AssistChip(
|
||||||
onClick = { text = history },
|
onClick = { text = history },
|
||||||
label = { Text(history, maxLines = 1) }
|
label = { AppText(history, maxLines = 1) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,11 +106,11 @@ fun SourceInputDialog(
|
|||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { if (text.isNotBlank()) onConfirm(text) }
|
onClick = { if (text.isNotBlank()) onConfirm(text) }
|
||||||
) { Text(stringResource(android.R.string.ok)) }
|
) { AppText(stringResource(android.R.string.ok)) }
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextButton(onClick = onDismissRequest) {
|
||||||
Text(stringResource(android.R.string.cancel))
|
AppText(stringResource(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -254,14 +255,14 @@ private fun ImportItemRow(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
supportingContent = {
|
supportingContent = {
|
||||||
Text(
|
AppText(
|
||||||
text = when (status) {
|
text = when (status) {
|
||||||
ImportStatus.New -> "新增"
|
ImportStatus.New -> "新增"
|
||||||
ImportStatus.Update -> "更新"
|
ImportStatus.Update -> "更新"
|
||||||
ImportStatus.Existing -> "已有"
|
ImportStatus.Existing -> "已有"
|
||||||
ImportStatus.Error -> "错误"
|
ImportStatus.Error -> "错误"
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = LegadoTheme.typography.labelMedium,
|
||||||
color = when (status) {
|
color = when (status) {
|
||||||
ImportStatus.New -> MaterialTheme.colorScheme.primary
|
ImportStatus.New -> MaterialTheme.colorScheme.primary
|
||||||
ImportStatus.Update -> MaterialTheme.colorScheme.secondary
|
ImportStatus.Update -> MaterialTheme.colorScheme.secondary
|
||||||
@@ -315,12 +316,12 @@ fun ImportBottomBar(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
OutlinedButton(onClick = onCancel) { Text("取消") }
|
OutlinedButton(onClick = onCancel) { AppText("取消") }
|
||||||
Button(
|
Button(
|
||||||
enabled = selectedCount > 0,
|
enabled = selectedCount > 0,
|
||||||
onClick = onConfirm
|
onClick = onConfirm
|
||||||
) {
|
) {
|
||||||
Text("导入")
|
AppText("导入")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,19 +15,11 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
|
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.PlainTooltip
|
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
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.animateFloatingActionButton
|
||||||
import androidx.compose.material3.rememberTooltipState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
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.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
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.AppScaffold
|
||||||
import io.legado.app.ui.widget.components.GlassTopAppBarDefaults
|
|
||||||
import io.legado.app.ui.widget.components.SelectionActions
|
import io.legado.app.ui.widget.components.SelectionActions
|
||||||
import io.legado.app.ui.widget.components.SelectionBottomBar
|
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.DynamicTopAppBar
|
||||||
|
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||||
|
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarScrollBehavior
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -52,28 +46,21 @@ fun <T> ListScaffold(
|
|||||||
onSearchQueryChange: (String) -> Unit,
|
onSearchQueryChange: (String) -> Unit,
|
||||||
searchPlaceholder: String = "搜索...",
|
searchPlaceholder: String = "搜索...",
|
||||||
topBarActions: @Composable RowScope.() -> Unit = {},
|
topBarActions: @Composable RowScope.() -> Unit = {},
|
||||||
bottomContent: @Composable (ColumnScope.(TopAppBarScrollBehavior) -> Unit)? = null,
|
bottomContent: @Composable (ColumnScope.(GlassTopAppBarScrollBehavior) -> Unit)? = null,
|
||||||
dropDownMenuContent: @Composable (ColumnScope.(dismiss: () -> Unit) -> Unit)? = null,
|
dropDownMenuContent: @Composable (ColumnScope.(dismiss: () -> Unit) -> Unit)? = null,
|
||||||
selectionActions: SelectionActions? = null,
|
selectionActions: SelectionActions? = null,
|
||||||
onAddClick: (() -> Unit)? = null,
|
onAddClick: (() -> Unit)? = null,
|
||||||
floatingActionButton: @Composable () -> Unit = {
|
floatingActionButton: @Composable () -> Unit = {
|
||||||
onAddClick?.let { onClick ->
|
onAddClick?.let { onClick ->
|
||||||
TooltipBox(
|
AppFloatingActionButton(
|
||||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
onClick = onClick,
|
||||||
TooltipAnchorPosition.Above
|
modifier = Modifier.animateFloatingActionButton(
|
||||||
|
visible = state.selectedIds.isEmpty(),
|
||||||
|
alignment = Alignment.BottomEnd,
|
||||||
),
|
),
|
||||||
tooltip = { PlainTooltip { Text("添加") } },
|
tooltipText = "添加"
|
||||||
state = rememberTooltipState(),
|
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
Icon(Icons.Default.Add, contentDescription = "Add")
|
||||||
modifier = Modifier.animateFloatingActionButton(
|
|
||||||
visible = state.selectedIds.isEmpty(),
|
|
||||||
alignment = Alignment.BottomEnd,
|
|
||||||
),
|
|
||||||
onClick = onClick
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Add, contentDescription = "Add")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-1
@@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
import io.legado.app.ui.theme.rememberOpaqueColorScheme
|
import io.legado.app.ui.theme.rememberOpaqueColorScheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -57,7 +58,7 @@ fun RoundDropdownMenuItem(
|
|||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalContentColor provides contentColor,
|
LocalContentColor provides contentColor,
|
||||||
LocalTextStyle provides MaterialTheme.typography.labelLarge
|
LocalTextStyle provides LegadoTheme.typography.labelLarge
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -37,6 +36,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ fun <T> RuleEditSheet(
|
|||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = { Text(title) },
|
title = { AppText(title) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = onDismissRequest) {
|
IconButton(onClick = onDismissRequest) {
|
||||||
Icon(
|
Icon(
|
||||||
@@ -99,7 +99,7 @@ fun <T> RuleEditSheet(
|
|||||||
}
|
}
|
||||||
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
|
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.copy_rule)) },
|
text = { AppText(stringResource(R.string.copy_rule)) },
|
||||||
leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) },
|
leadingIcon = { Icon(Icons.AutoMirrored.Filled.NoteAdd, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onCopy(getCurrentEntity())
|
onCopy(getCurrentEntity())
|
||||||
@@ -107,7 +107,7 @@ fun <T> RuleEditSheet(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.paste_rule)) },
|
text = { AppText(stringResource(R.string.paste_rule)) },
|
||||||
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
leadingIcon = { Icon(Icons.Default.ContentPaste, null) },
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -136,20 +136,20 @@ fun <T> RuleEditSheet(
|
|||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = name,
|
value = name,
|
||||||
onValueChange = { name = it },
|
onValueChange = { name = it },
|
||||||
label = { Text(stringResource(R.string.name)) },
|
label = { AppText(stringResource(R.string.name)) },
|
||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = rule1,
|
value = rule1,
|
||||||
onValueChange = { rule1 = it },
|
onValueChange = { rule1 = it },
|
||||||
label = { Text(label1) }
|
label = { AppText(label1) }
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = rule2,
|
value = rule2,
|
||||||
onValueChange = { rule2 = it },
|
onValueChange = { rule2 = it },
|
||||||
label = { Text(label2) },
|
label = { AppText(label2) },
|
||||||
minLines = 3
|
minLines = 3
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,20 +10,12 @@ import androidx.compose.material3.AlertDialog
|
|||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.PlainTooltip
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
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.animateFloatingActionButton
|
||||||
import androidx.compose.material3.rememberTooltipState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -34,9 +26,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.ui.widget.components.ActionItem
|
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.SelectionActions
|
||||||
import io.legado.app.ui.widget.components.list.ListScaffold
|
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.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)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -49,7 +44,7 @@ fun <T> RuleListScaffold(
|
|||||||
onSearchQueryChange: (String) -> Unit,
|
onSearchQueryChange: (String) -> Unit,
|
||||||
searchPlaceholder: String = "搜索...",
|
searchPlaceholder: String = "搜索...",
|
||||||
topBarActions: @Composable RowScope.() -> Unit = {},
|
topBarActions: @Composable RowScope.() -> Unit = {},
|
||||||
bottomContent: @Composable (ColumnScope.(TopAppBarScrollBehavior) -> Unit)? = null,
|
bottomContent: @Composable (ColumnScope.(GlassTopAppBarScrollBehavior) -> Unit)? = null,
|
||||||
dropDownMenuContent: (@Composable ColumnScope.(dismiss: () -> Unit) -> Unit)? = null,
|
dropDownMenuContent: (@Composable ColumnScope.(dismiss: () -> Unit) -> Unit)? = null,
|
||||||
onClearSelection: () -> Unit,
|
onClearSelection: () -> Unit,
|
||||||
onSelectAll: () -> Unit,
|
onSelectAll: () -> Unit,
|
||||||
@@ -59,22 +54,15 @@ fun <T> RuleListScaffold(
|
|||||||
onAddClick: (() -> Unit)? = null,
|
onAddClick: (() -> Unit)? = null,
|
||||||
floatingActionButton: @Composable () -> Unit = {
|
floatingActionButton: @Composable () -> Unit = {
|
||||||
onAddClick?.let { onClick ->
|
onAddClick?.let { onClick ->
|
||||||
TooltipBox(
|
AppFloatingActionButton(
|
||||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
onClick = onClick,
|
||||||
TooltipAnchorPosition.Above
|
modifier = Modifier.animateFloatingActionButton(
|
||||||
|
visible = state.selectedIds.isEmpty(),
|
||||||
|
alignment = Alignment.BottomEnd,
|
||||||
),
|
),
|
||||||
tooltip = { PlainTooltip { Text("添加") } },
|
tooltipText = "添加"
|
||||||
state = rememberTooltipState(),
|
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
Icon(Icons.Default.Add, contentDescription = "Add")
|
||||||
modifier = Modifier.animateFloatingActionButton(
|
|
||||||
visible = state.selectedIds.isEmpty(),
|
|
||||||
alignment = Alignment.BottomEnd,
|
|
||||||
),
|
|
||||||
onClick = onClick
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Add, contentDescription = "Add")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -86,8 +74,8 @@ fun <T> RuleListScaffold(
|
|||||||
if (showDeleteConfirmDialog) {
|
if (showDeleteConfirmDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { showDeleteConfirmDialog = false },
|
onDismissRequest = { showDeleteConfirmDialog = false },
|
||||||
title = { Text(stringResource(R.string.delete)) },
|
title = { AppText(stringResource(R.string.delete)) },
|
||||||
text = { Text(stringResource(R.string.del_msg)) },
|
text = { AppText(stringResource(R.string.del_msg)) },
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -98,12 +86,12 @@ fun <T> RuleListScaffold(
|
|||||||
contentColor = MaterialTheme.colorScheme.error
|
contentColor = MaterialTheme.colorScheme.error
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.ok))
|
AppText(stringResource(R.string.ok))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { showDeleteConfirmDialog = false }) {
|
TextButton(onClick = { showDeleteConfirmDialog = false }) {
|
||||||
Text(stringResource(R.string.cancel))
|
AppText(stringResource(R.string.cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+30
-16
@@ -7,6 +7,10 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
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
|
@Composable
|
||||||
fun ClickableSettingItem(
|
fun ClickableSettingItem(
|
||||||
@@ -19,20 +23,30 @@ fun ClickableSettingItem(
|
|||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
SettingItem(
|
val composeEngine = LegadoTheme.composeEngine
|
||||||
modifier = modifier,
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
title = title,
|
SuperArrow(
|
||||||
description = description,
|
title = title,
|
||||||
option = option,
|
summary = description,
|
||||||
imageVector = imageVector,
|
insideMargin = BasicComponentDefaults.InsideMargin,
|
||||||
trailingContent = trailingContent ?: {
|
onClick = onClick
|
||||||
Icon(
|
)
|
||||||
imageVector = Icons.Default.ChevronRight,
|
} else {
|
||||||
contentDescription = null,
|
SettingItem(
|
||||||
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
modifier = modifier,
|
||||||
)
|
title = title,
|
||||||
},
|
description = description,
|
||||||
onClick = onClick,
|
option = option,
|
||||||
onLongClick = onLongClick
|
imageVector = imageVector,
|
||||||
)
|
trailingContent = trailingContent ?: {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ChevronRight,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
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.button.SmallOutlinedIconButton
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
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.menuItem.RoundDropdownMenuItem
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -66,7 +66,7 @@ fun CompactDropdownSettingItem(
|
|||||||
dropdownMenu = { onDismiss ->
|
dropdownMenu = { onDismiss ->
|
||||||
displayEntries.forEachIndexed { index, display ->
|
displayEntries.forEachIndexed { index, display ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text(display) },
|
text = { AppText(display) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onValueChange(entryValues[index])
|
onValueChange(entryValues[index])
|
||||||
onDismiss()
|
onDismiss()
|
||||||
|
|||||||
+101
-40
@@ -1,15 +1,17 @@
|
|||||||
package io.legado.app.ui.widget.components.settingItem
|
package io.legado.app.ui.widget.components.settingItem
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.text.input.rememberTextFieldState
|
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.material.icons.filled.Replay
|
import androidx.compose.material.icons.filled.Replay
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -21,7 +23,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
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.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
|
@Composable
|
||||||
fun InputSettingItem(
|
fun InputSettingItem(
|
||||||
@@ -31,6 +38,7 @@ fun InputSettingItem(
|
|||||||
description: String? = null,
|
description: String? = null,
|
||||||
onConfirm: (String) -> Unit
|
onConfirm: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
|
// 1. 状态统一提升到外部,两套引擎共用
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
val state = rememberTextFieldState(initialText = value)
|
val state = rememberTextFieldState(initialText = value)
|
||||||
|
|
||||||
@@ -42,51 +50,104 @@ fun InputSettingItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingItem(
|
val composeEngine = LegadoTheme.composeEngine
|
||||||
title = title,
|
|
||||||
description = description,
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
option = value,
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
expanded = expanded,
|
BasicComponent(
|
||||||
onExpandChange = { expanded = it },
|
title = title,
|
||||||
expandContent = {
|
summary = value,
|
||||||
TextField(
|
onClick = { expanded = !expanded }
|
||||||
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
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
AnimatedVisibility(visible = expanded) {
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Column(
|
||||||
horizontalArrangement = Arrangement.End
|
modifier = Modifier
|
||||||
) {
|
.fillMaxWidth()
|
||||||
SmallTextButton(
|
.padding(horizontal = 16.dp, vertical = 4.dp)
|
||||||
text = "默认",
|
) {
|
||||||
icon = Icons.Default.Replay,
|
MiuixTextField(
|
||||||
onClick = {
|
state = state,
|
||||||
state.edit { replace(0, length, defaultValue.toString()) }
|
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,
|
} else {
|
||||||
onClick = {
|
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())
|
onConfirm(state.text.toString())
|
||||||
expanded = false
|
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
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
+61
-28
@@ -4,12 +4,16 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
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.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
|
@Composable
|
||||||
fun DropdownListSettingItem(
|
fun DropdownListSettingItem(
|
||||||
@@ -21,33 +25,62 @@ fun DropdownListSettingItem(
|
|||||||
imageVector: ImageVector? = null,
|
imageVector: ImageVector? = null,
|
||||||
onValueChange: (String) -> Unit
|
onValueChange: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val currentEntry = displayEntries.getOrNull(entryValues.indexOf(selectedValue)) ?: selectedValue
|
val composeEngine = LegadoTheme.composeEngine
|
||||||
|
|
||||||
SettingItem(
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
title = title,
|
val selectedIndex = entryValues.indexOf(selectedValue).coerceAtLeast(0)
|
||||||
description = description,
|
val spinnerItems = displayEntries.map { display ->
|
||||||
option = currentEntry,
|
SpinnerEntry(title = display)
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.ListItemDefaults
|
import androidx.compose.material3.ListItemDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
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.menuItem.RoundDropdownMenu
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -59,7 +60,7 @@ fun SettingItem(
|
|||||||
var showMenu by remember { mutableStateOf(false) }
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
val isExpandable = expandContent != null && onExpandChange != null
|
val isExpandable = expandContent != null && onExpandChange != null
|
||||||
|
|
||||||
GlassCard(
|
SettingCard(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = shape,
|
shape = shape,
|
||||||
@@ -101,25 +102,25 @@ fun SettingItem(
|
|||||||
}
|
}
|
||||||
} else null,
|
} else null,
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
AppText(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = LegadoTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
supportingContent = if (description != null || option != null) {
|
supportingContent = if (description != null || option != null) {
|
||||||
{
|
{
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||||
description?.let {
|
description?.let {
|
||||||
Text(
|
AppText(
|
||||||
it,
|
it,
|
||||||
style = MaterialTheme.typography.bodySmallEmphasized,
|
style = LegadoTheme.typography.bodySmallEmphasized,
|
||||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
option?.let {
|
option?.let {
|
||||||
Text(
|
AppText(
|
||||||
it,
|
it,
|
||||||
style = MaterialTheme.typography.labelMediumEmphasized,
|
style = LegadoTheme.typography.labelMediumEmphasized,
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+182
-71
@@ -1,12 +1,15 @@
|
|||||||
package io.legado.app.ui.widget.components.settingItem
|
package io.legado.app.ui.widget.components.settingItem
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.text.input.TextFieldLineLimits
|
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.material.icons.filled.RestartAlt
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -29,7 +31,13 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
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.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
|
@Composable
|
||||||
fun SliderSettingItem(
|
fun SliderSettingItem(
|
||||||
@@ -45,85 +53,188 @@ fun SliderSettingItem(
|
|||||||
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
var isInputMode 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())
|
val textFieldState = rememberTextFieldState(initialText = value.toInt().toString())
|
||||||
|
|
||||||
SettingItem(
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
title = title,
|
|
||||||
color = color ?: MaterialTheme.colorScheme.surfaceContainerLow,
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
option = description,
|
BasicComponent(
|
||||||
expanded = expanded,
|
title = title,
|
||||||
onExpandChange = { expanded = it },
|
summary = description,
|
||||||
expandContent = {
|
onClick = { expanded = !expanded }
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
)
|
||||||
AnimatedContent(
|
|
||||||
targetState = isInputMode,
|
AnimatedVisibility(visible = expanded) {
|
||||||
label = "input_slider_switch"
|
Column(
|
||||||
) { targetInputMode ->
|
modifier = Modifier
|
||||||
if (targetInputMode) {
|
.fillMaxWidth()
|
||||||
TextField(
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
state = textFieldState,
|
) {
|
||||||
lineLimits = TextFieldLineLimits.SingleLine,
|
AnimatedContent(
|
||||||
label = { Text("输入数值 (${valueRange.start.toInt()}-${valueRange.endInclusive.toInt()})") },
|
targetState = isInputMode,
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
label = "input_slider_switch"
|
||||||
modifier = Modifier
|
) { targetInputMode ->
|
||||||
.fillMaxWidth()
|
if (targetInputMode) {
|
||||||
.heightIn(min = 48.dp),
|
MiuixTextField(
|
||||||
contentPadding = PaddingValues(
|
state = textFieldState,
|
||||||
top = 4.dp,
|
lineLimits = TextFieldLineLimits.SingleLine,
|
||||||
bottom = 4.dp,
|
label = "输入数值 (${valueRange.start.toInt()}-${valueRange.endInclusive.toInt()})",
|
||||||
start = 12.dp,
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
end = 12.dp
|
modifier = Modifier.fillMaxWidth(),
|
||||||
),
|
inputTransformation = {
|
||||||
inputTransformation = {
|
val newText = asCharSequence().toString()
|
||||||
val newText = asCharSequence().toString()
|
newText.toFloatOrNull()?.let { num ->
|
||||||
newText.toFloatOrNull()?.let { num ->
|
onValueChange(
|
||||||
onValueChange(
|
num.coerceIn(
|
||||||
num.coerceIn(
|
valueRange.start,
|
||||||
valueRange.start,
|
valueRange.endInclusive
|
||||||
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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+41
-14
@@ -3,7 +3,12 @@ package io.legado.app.ui.widget.components.settingItem
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
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
|
@Composable
|
||||||
fun SwitchSettingItem(
|
fun SwitchSettingItem(
|
||||||
@@ -15,18 +20,40 @@ fun SwitchSettingItem(
|
|||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
onCheckedChange: (Boolean) -> Unit
|
onCheckedChange: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
SettingItem(
|
val composeEngine = LegadoTheme.composeEngine
|
||||||
title = title,
|
|
||||||
description = description,
|
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||||
imageVector = imageVector,
|
val toggleAction = {
|
||||||
color = color,
|
if (enabled) onCheckedChange(!checked)
|
||||||
onClick = { if (enabled) onCheckedChange(!checked) },
|
|
||||||
trailingContent = {
|
|
||||||
IconSwitch(
|
|
||||||
checked = checked,
|
|
||||||
onCheckedChange = onCheckedChange,
|
|
||||||
enabled = enabled
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<String>,
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user