Merge branch 'miuix-dev'
# Conflicts: # app/version.properties
This commit is contained in:
121 files changed
+5128
-2921
No files matched your search
@@ -285,4 +285,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,6 @@ 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.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 +28,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 +58,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 +80,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
|
||||||
@@ -91,16 +90,14 @@ fun AboutScreen(
|
|||||||
.wrapContentWidth(Alignment.CenterHorizontally))
|
.wrapContentWidth(Alignment.CenterHorizontally))
|
||||||
TextCard(
|
TextCard(
|
||||||
text = versionName,
|
text = versionName,
|
||||||
backgroundColor = colorScheme.tertiaryContainer,
|
|
||||||
contentColor = colorScheme.onTertiaryContainer,
|
|
||||||
cornerRadius = 8.dp,
|
cornerRadius = 8.dp,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.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,19 +30,23 @@ 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.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
|
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||||
|
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
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AppLogSheet(
|
fun AppLogSheet(
|
||||||
|
show: Boolean,
|
||||||
onDismissRequest: () -> Unit
|
onDismissRequest: () -> Unit
|
||||||
) {
|
) {
|
||||||
var logs by remember { mutableStateOf(AppLog.logs) }
|
var logs by remember { mutableStateOf(AppLog.logs) }
|
||||||
var showStackTrace by remember { mutableStateOf<String?>(null) }
|
var showStackTrace by remember { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
GlassModalBottomSheet(
|
AppModalBottomSheet(
|
||||||
|
show = show,
|
||||||
onDismissRequest = onDismissRequest
|
onDismissRequest = onDismissRequest
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@@ -52,9 +55,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 +85,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 +113,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,8 @@ 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.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 +97,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 +127,7 @@ fun AllBookmarkScreen(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 JSON") },
|
text = "导出 JSON",
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
pendingExportIsMd = false
|
pendingExportIsMd = false
|
||||||
@@ -140,7 +135,7 @@ fun AllBookmarkScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 Markdown") },
|
text = "导出 Markdown",
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
pendingExportIsMd = true
|
pendingExportIsMd = true
|
||||||
@@ -242,22 +237,21 @@ fun AllBookmarkScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showBottomSheet && editingBookmark != null) {
|
BookmarkEditSheet(
|
||||||
BookmarkEditSheet(
|
show = showBottomSheet && editingBookmark != null,
|
||||||
bookmark = editingBookmark!!,
|
bookmark = editingBookmark ?: Bookmark(),
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
showBottomSheet = false
|
showBottomSheet = false
|
||||||
editingBookmark = null
|
editingBookmark = null
|
||||||
},
|
},
|
||||||
onSave = { updatedBookmark ->
|
onSave = { updatedBookmark ->
|
||||||
viewModel.updateBookmark(updatedBookmark)
|
viewModel.updateBookmark(updatedBookmark)
|
||||||
showBottomSheet = false
|
showBottomSheet = false
|
||||||
},
|
},
|
||||||
onDelete = { bookmarkToDelete ->
|
onDelete = { bookmarkToDelete ->
|
||||||
viewModel.deleteBookmark(bookmarkToDelete)
|
viewModel.deleteBookmark(bookmarkToDelete)
|
||||||
showBottomSheet = false
|
showBottomSheet = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -93,7 +90,10 @@ import io.legado.app.ui.widget.components.card.TextCard
|
|||||||
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.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.AppModalBottomSheet
|
||||||
|
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
|
||||||
@@ -180,112 +180,111 @@ fun ExploreShowScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showGridCountSheet) {
|
|
||||||
|
|
||||||
GlassModalBottomSheet(
|
AppModalBottomSheet(
|
||||||
|
show = showGridCountSheet,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp),
|
||||||
|
onDismissRequest = { showGridCountSheet = false }
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(16.dp),
|
.fillMaxWidth()
|
||||||
onDismissRequest = { showGridCountSheet = false }
|
.padding(bottom = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Row(
|
AppText(
|
||||||
modifier = Modifier
|
text = "布局列数",
|
||||||
.fillMaxWidth()
|
style = LegadoTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)
|
||||||
.padding(bottom = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "布局列数",
|
|
||||||
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
|
||||||
|
|
||||||
TextCard(
|
|
||||||
text = "$gridColumnCount 列",
|
|
||||||
textStyle = MaterialTheme.typography.titleSmall,
|
|
||||||
verticalPadding = 4.dp,
|
|
||||||
horizontalPadding = 12.dp,
|
|
||||||
cornerRadius = 12.dp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider(
|
|
||||||
value = gridColumnCount.toFloat(),
|
|
||||||
onValueChange = {
|
|
||||||
val col = it.toInt().coerceIn(1, 10)
|
|
||||||
viewModel.saveGridCount(col)
|
|
||||||
},
|
|
||||||
valueRange = 1f..10f,
|
|
||||||
steps = 8,
|
|
||||||
modifier = Modifier.padding(horizontal = 20.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
|
||||||
OutlinedButton(
|
TextCard(
|
||||||
onClick = { showGridCountSheet = false },
|
text = "$gridColumnCount 列",
|
||||||
modifier = Modifier
|
textStyle = LegadoTheme.typography.titleSmall,
|
||||||
.fillMaxWidth()
|
verticalPadding = 4.dp,
|
||||||
.padding(horizontal = 16.dp)
|
horizontalPadding = 12.dp,
|
||||||
) {
|
cornerRadius = 12.dp
|
||||||
Text("完成")
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slider(
|
||||||
|
value = gridColumnCount.toFloat(),
|
||||||
|
onValueChange = {
|
||||||
|
val col = it.toInt().coerceIn(1, 10)
|
||||||
|
viewModel.saveGridCount(col)
|
||||||
|
},
|
||||||
|
valueRange = 1f..10f,
|
||||||
|
steps = 8,
|
||||||
|
modifier = Modifier.padding(horizontal = 20.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(24.dp))
|
||||||
|
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = { showGridCountSheet = false },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
AppText("完成")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showKindSheet) {
|
|
||||||
GlassModalBottomSheet(
|
|
||||||
onDismissRequest = { showKindSheet = false }
|
|
||||||
) {
|
|
||||||
|
|
||||||
var kindQuery by remember { mutableStateOf("") }
|
AppModalBottomSheet(
|
||||||
|
show = showKindSheet,
|
||||||
|
onDismissRequest = { showKindSheet = false }
|
||||||
|
) {
|
||||||
|
|
||||||
SearchBarSection(
|
var kindQuery by remember { mutableStateOf("") }
|
||||||
query = kindQuery,
|
|
||||||
backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
|
||||||
onQueryChange = { kindQuery = it },
|
|
||||||
placeholder = "选择或搜索分类",
|
|
||||||
)
|
|
||||||
|
|
||||||
val filteredKinds = remember(kindQuery, kinds) {
|
SearchBarSection(
|
||||||
if (kindQuery.isBlank()) kinds
|
query = kindQuery,
|
||||||
else kinds.filter { kind ->
|
backgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
kind.title.contains(kindQuery, ignoreCase = true) ||
|
onQueryChange = { kindQuery = it },
|
||||||
(kind.url?.contains(kindQuery, ignoreCase = true) == true)
|
placeholder = "选择或搜索分类",
|
||||||
}
|
)
|
||||||
|
|
||||||
|
val filteredKinds = remember(kindQuery, kinds) {
|
||||||
|
if (kindQuery.isBlank()) kinds
|
||||||
|
else kinds.filter { kind ->
|
||||||
|
kind.title.contains(kindQuery, ignoreCase = true) ||
|
||||||
|
(kind.url?.contains(kindQuery, ignoreCase = true) == true)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(3),
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(16.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
modifier = Modifier.weight(1f, fill = false)
|
modifier = Modifier.weight(1f, fill = false)
|
||||||
) {
|
) {
|
||||||
itemsIndexed(
|
itemsIndexed(
|
||||||
items = filteredKinds,
|
items = filteredKinds,
|
||||||
key = { index, kind -> "${kind.url ?: kind.title}_$index" },
|
key = { index, kind -> "${kind.url ?: kind.title}_$index" },
|
||||||
span = { _, kind ->
|
span = { _, kind ->
|
||||||
val isClickable = !kind.url.isNullOrBlank()
|
val isClickable = !kind.url.isNullOrBlank()
|
||||||
if (isClickable) GridItemSpan(1) else GridItemSpan(3)
|
if (isClickable) GridItemSpan(1) else GridItemSpan(3)
|
||||||
|
}
|
||||||
|
) { _, kind ->
|
||||||
|
KindGridItem(
|
||||||
|
modifier = Modifier.animateItem(),
|
||||||
|
kind = kind,
|
||||||
|
currentTitle = selectedTitle ?: title,
|
||||||
|
onClick = {
|
||||||
|
showKindSheet = false
|
||||||
|
viewModel.switchExploreUrl(kind)
|
||||||
}
|
}
|
||||||
) { _, kind ->
|
)
|
||||||
KindGridItem(
|
|
||||||
modifier = Modifier.animateItem(),
|
|
||||||
kind = kind,
|
|
||||||
currentTitle = selectedTitle ?: title,
|
|
||||||
onClick = {
|
|
||||||
showKindSheet = false
|
|
||||||
viewModel.switchExploreUrl(kind)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AppScaffold(
|
AppScaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
@@ -294,14 +293,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(),
|
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
TopbarNavigationButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
@@ -346,7 +338,7 @@ fun ExploreShowScreen(
|
|||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("全部显示") },
|
text = "全部显示",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.SHOW_ALL)
|
viewModel.setFilterState(BookFilterState.SHOW_ALL)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -358,7 +350,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("隐藏已在书架的同源书籍") },
|
text = "隐藏已在书架的同源书籍",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.HIDE_IN_SHELF)
|
viewModel.setFilterState(BookFilterState.HIDE_IN_SHELF)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -370,7 +362,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("隐藏已在书架的非同源书籍") },
|
text = "隐藏已在书架的非同源书籍",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.HIDE_SAME_NAME_AUTHOR)
|
viewModel.setFilterState(BookFilterState.HIDE_SAME_NAME_AUTHOR)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -382,7 +374,7 @@ fun ExploreShowScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("只显示不在书架的书籍") },
|
text = "只显示不在书架的书籍",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setFilterState(BookFilterState.SHOW_NOT_IN_SHELF_ONLY)
|
viewModel.setFilterState(BookFilterState.SHOW_NOT_IN_SHELF_ONLY)
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -509,7 +501,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 +568,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 +604,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 +646,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 +676,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 +693,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 +737,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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ 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.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
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
|
||||||
@@ -18,11 +17,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
|
||||||
@@ -39,9 +36,10 @@ 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.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.AppModalBottomSheet
|
||||||
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
|
||||||
@@ -55,11 +53,12 @@ import java.io.FileOutputStream
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun GroupEditSheet(
|
fun GroupEditSheet(
|
||||||
|
show: Boolean,
|
||||||
group: BookGroup? = null,
|
group: BookGroup? = null,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
viewModel: GroupViewModel = koinViewModel()
|
viewModel: GroupViewModel = koinViewModel()
|
||||||
) {
|
) {
|
||||||
GlassModalBottomSheet(onDismissRequest = onDismissRequest) {
|
AppModalBottomSheet(show = show, onDismissRequest = onDismissRequest) {
|
||||||
GroupEditContent(
|
GroupEditContent(
|
||||||
group = group,
|
group = group,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
@@ -108,17 +107,9 @@ fun GroupEditContent(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
.padding(bottom = 16.dp)
|
|
||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState()),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.group_edit),
|
|
||||||
style = MaterialTheme.typography.titleLarge,
|
|
||||||
modifier = Modifier.padding(vertical = 16.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.Top,
|
verticalAlignment = Alignment.Top,
|
||||||
@@ -138,7 +129,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 +197,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 +226,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
|
||||||
@@ -88,7 +88,8 @@ import io.legado.app.ui.widget.components.button.SmallTonalIconButton
|
|||||||
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.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.AppModalBottomSheet
|
||||||
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -198,42 +199,41 @@ fun RemoteBookScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showSheet != null) {
|
AppModalBottomSheet(
|
||||||
GlassModalBottomSheet(
|
show = showSheet != null,
|
||||||
onDismissRequest = { showSheet = null }
|
onDismissRequest = { showSheet = null }
|
||||||
) {
|
) {
|
||||||
when (val state = showSheet) {
|
when (val state = showSheet) {
|
||||||
is RemoteBookSheet.Servers -> {
|
is RemoteBookSheet.Servers -> {
|
||||||
ServersSheetContent(
|
ServersSheetContent(
|
||||||
servers = uiState.servers,
|
servers = uiState.servers,
|
||||||
selectedServerId = uiState.selectedServerId,
|
selectedServerId = uiState.selectedServerId,
|
||||||
onSelect = {
|
onSelect = {
|
||||||
viewModel.selectServer(it)
|
viewModel.selectServer(it)
|
||||||
showSheet = null
|
showSheet = null
|
||||||
},
|
},
|
||||||
onEdit = { showSheet = RemoteBookSheet.ServerConfig(it) },
|
onEdit = { showSheet = RemoteBookSheet.ServerConfig(it) },
|
||||||
onDelete = { viewModel.deleteServer(it) },
|
onDelete = { viewModel.deleteServer(it) },
|
||||||
onAdd = { showSheet = RemoteBookSheet.ServerConfig(null) },
|
onAdd = { showSheet = RemoteBookSheet.ServerConfig(null) },
|
||||||
onDefault = {
|
onDefault = {
|
||||||
viewModel.selectServer(AppConst.DEFAULT_WEBDAV_ID)
|
viewModel.selectServer(AppConst.DEFAULT_WEBDAV_ID)
|
||||||
showSheet = null
|
showSheet = null
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
is RemoteBookSheet.ServerConfig -> {
|
|
||||||
ServerConfigSheetContent(
|
|
||||||
server = state.server,
|
|
||||||
onSave = {
|
|
||||||
viewModel.saveServer(it)
|
|
||||||
showSheet = RemoteBookSheet.Servers
|
|
||||||
},
|
|
||||||
onCancel = { showSheet = RemoteBookSheet.Servers }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is RemoteBookSheet.ServerConfig -> {
|
||||||
|
ServerConfigSheetContent(
|
||||||
|
server = state.server,
|
||||||
|
onSave = {
|
||||||
|
viewModel.saveServer(it)
|
||||||
|
showSheet = RemoteBookSheet.Servers
|
||||||
|
},
|
||||||
|
onCancel = { showSheet = RemoteBookSheet.Servers }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ fun RemoteBookScreen(
|
|||||||
},
|
},
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("按名称排序") },
|
text = "按名称排序",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.toggleSort(RemoteBookSort.Name)
|
viewModel.toggleSort(RemoteBookSort.Name)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -271,7 +271,7 @@ fun RemoteBookScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("按时间排序") },
|
text = "按时间排序",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.toggleSort(RemoteBookSort.Default)
|
viewModel.toggleSort(RemoteBookSort.Default)
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -381,9 +381,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 +447,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 +462,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 +514,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 +531,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 +539,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 +547,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 +571,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 +587,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 +625,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 +716,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 +732,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 +743,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
|
||||||
|
|||||||
@@ -32,18 +32,13 @@ import androidx.compose.material.icons.filled.Schedule
|
|||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.filled.Timeline
|
import androidx.compose.material.icons.filled.Timeline
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Card
|
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
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.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
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,15 +73,15 @@ 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.widget.components.AnimatedTextLine
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
|
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.SectionHeader
|
|
||||||
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.AppIconButton
|
||||||
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.GlassCard
|
||||||
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.heatmap.HeatmapCalendarTopBar
|
import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarTopBar
|
||||||
import io.legado.app.ui.widget.components.heatmap.HeatmapConfig
|
import io.legado.app.ui.widget.components.heatmap.HeatmapConfig
|
||||||
@@ -98,9 +93,14 @@ import io.legado.app.ui.widget.components.heatmap.WeekdayLabelsColumn
|
|||||||
import io.legado.app.ui.widget.components.heatmap.rememberDateRange
|
import io.legado.app.ui.widget.components.heatmap.rememberDateRange
|
||||||
import io.legado.app.ui.widget.components.heatmap.rememberDaysInRange
|
import io.legado.app.ui.widget.components.heatmap.rememberDaysInRange
|
||||||
import io.legado.app.ui.widget.components.heatmap.rememberWeeks
|
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.icon.AppIcon
|
||||||
|
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||||
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.AnimatedTextLine
|
||||||
|
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 +148,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 -> "汇总视图"
|
||||||
@@ -167,7 +163,7 @@ fun ReadRecordScreen(
|
|||||||
TopbarNavigationButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = {
|
AppIconButton(onClick = {
|
||||||
val newMode = when (displayMode) {
|
val newMode = when (displayMode) {
|
||||||
DisplayMode.AGGREGATE -> DisplayMode.TIMELINE
|
DisplayMode.AGGREGATE -> DisplayMode.TIMELINE
|
||||||
DisplayMode.TIMELINE -> DisplayMode.LATEST
|
DisplayMode.TIMELINE -> DisplayMode.LATEST
|
||||||
@@ -181,13 +177,16 @@ fun ReadRecordScreen(
|
|||||||
DisplayMode.LATEST -> Icons.AutoMirrored.Filled.List
|
DisplayMode.LATEST -> Icons.AutoMirrored.Filled.List
|
||||||
}
|
}
|
||||||
val description = if (displayMode == DisplayMode.AGGREGATE) "Switch to Timeline" else "Switch to Aggregate"
|
val description = if (displayMode == DisplayMode.AGGREGATE) "Switch to Timeline" else "Switch to Aggregate"
|
||||||
Icon(icon, description)
|
AppIcon(icon, description)
|
||||||
}
|
}
|
||||||
IconButton(onClick = { showCalendar = !showCalendar }) {
|
AppIconButton(onClick = { showCalendar = !showCalendar }) {
|
||||||
Icon(Icons.Default.CalendarMonth, contentDescription = "Toggle Calendar")
|
AppIcon(
|
||||||
|
Icons.Default.CalendarMonth,
|
||||||
|
contentDescription = "Toggle Calendar"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
IconButton(onClick = { showSearch = !showSearch }) {
|
AppIconButton(onClick = { showSearch = !showSearch }) {
|
||||||
Icon(Icons.Default.Search, contentDescription = null)
|
AppIcon(Icons.Default.Search, contentDescription = null)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior
|
scrollBehavior = scrollBehavior
|
||||||
@@ -271,10 +270,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 +288,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,30 +310,29 @@ fun ReadRecordScreen(
|
|||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
pendingDeleteAction = null
|
pendingDeleteAction = null
|
||||||
}) {
|
}) {
|
||||||
Text("取消")
|
AppText("取消")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showCalendar) {
|
AppModalBottomSheet(
|
||||||
GlassModalBottomSheet(
|
show = showCalendar,
|
||||||
onDismissRequest = { showCalendar = false }
|
onDismissRequest = { showCalendar = false }
|
||||||
) {
|
) {
|
||||||
HeatmapCalendarSection(
|
HeatmapCalendarSection(
|
||||||
dailyReadCounts = state.dailyReadCounts,
|
dailyReadCounts = state.dailyReadCounts,
|
||||||
dailyReadTimes = state.dailyReadTimes,
|
dailyReadTimes = state.dailyReadTimes,
|
||||||
selectedDate = state.selectedDate,
|
selectedDate = state.selectedDate,
|
||||||
onDateSelected = { date ->
|
onDateSelected = { date ->
|
||||||
viewModel.setSelectedDate(date)
|
viewModel.setSelectedDate(date)
|
||||||
showCalendar = false
|
showCalendar = false
|
||||||
},
|
},
|
||||||
onClearDate = {
|
onClearDate = {
|
||||||
viewModel.setSelectedDate(null)
|
viewModel.setSelectedDate(null)
|
||||||
showCalendar = false
|
showCalendar = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -346,10 +344,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 +365,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 +384,12 @@ fun ReadRecordScreen(
|
|||||||
mergeDialogData = null
|
mergeDialogData = null
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text("合并")
|
AppText("合并")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
TextButton(onClick = { mergeDialogData = null }) {
|
TextButton(onClick = { mergeDialogData = null }) {
|
||||||
Text("取消")
|
AppText("取消")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -686,21 +684,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 +714,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 +781,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 +793,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 +845,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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -872,28 +870,27 @@ fun DateHeader(
|
|||||||
date: String,
|
date: String,
|
||||||
dailyTotalTime: Long? = null
|
dailyTotalTime: Long? = null
|
||||||
) {
|
) {
|
||||||
val dateText = formatFriendlyDate(date)
|
CollapsibleHeader(
|
||||||
SectionHeader(
|
showIcon = false,
|
||||||
|
isCollapsed = false,
|
||||||
|
onToggle = { },
|
||||||
|
title = "",
|
||||||
titleContent = {
|
titleContent = {
|
||||||
Column {
|
val dateText = formatFriendlyDate(date)
|
||||||
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 = LegadoTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
dailyTotalTime?.let { total ->
|
||||||
|
AppText(
|
||||||
|
text = "已读 ${formatDuring(total)}",
|
||||||
|
style = LegadoTheme.typography.bodySmall,
|
||||||
|
color = LegadoTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
|
|
||||||
dailyTotalTime?.let { total ->
|
|
||||||
Text(
|
|
||||||
text = "已读 ${formatDuring(total)}",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
detailContent = null,
|
|
||||||
horizontalArrangement = Arrangement.Start
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,14 +912,12 @@ fun ReadingSummaryCard(
|
|||||||
|
|
||||||
val totalDurationMinutes = totalTimeMillis / 60000
|
val totalDurationMinutes = totalTimeMillis / 60000
|
||||||
|
|
||||||
Card(
|
GlassCard(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
colors = CardDefaults.cardColors(
|
containerColor = LegadoTheme.colorScheme.surfaceContainer
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceContainer
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -934,28 +929,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 = LegadoTheme.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 = LegadoTheme.colorScheme.primary,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
Text(
|
AppText(
|
||||||
text = " 本书",
|
text = " 本书",
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = LegadoTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,10 +960,10 @@ 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 = LegadoTheme.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,10 +307,10 @@ 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 = LegadoTheme.colorScheme.primary,
|
||||||
modifier = Modifier.align(Alignment.Center)
|
modifier = Modifier.align(Alignment.Center)
|
||||||
)
|
)
|
||||||
SmallAnimatedActionButton(
|
SmallAnimatedActionButton(
|
||||||
@@ -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 = "使用替换规则",
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = useReplace, onCheckedChange = null)
|
Checkbox(checked = useReplace, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleUseReplace() }
|
onClick = { viewModel.toggleUseReplace() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("显示字数") },
|
text = "显示字数",
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = showWordCount, onCheckedChange = null)
|
Checkbox(checked = showWordCount, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleShowWordCount() }
|
onClick = { viewModel.toggleShowWordCount() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("反转目录") },
|
text = "反转目录",
|
||||||
onClick = { viewModel.reverseToc() }
|
onClick = { viewModel.reverseToc() }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("替换规则") },
|
text = "替换规则",
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenReplaceRule(null)
|
onOpenReplaceRule(null)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("新建替换规则") },
|
text = "新建替换规则",
|
||||||
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 = "本地书籍目录规则",
|
||||||
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 = "拆分超长章节",
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(
|
Checkbox(
|
||||||
checked = viewModel.isSplitLongChapter,
|
checked = viewModel.isSplitLongChapter,
|
||||||
@@ -386,7 +387,7 @@ fun TocScreen(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出书签为JSON") },
|
text = "导出书签为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 = "导出书签为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 = "展开所有卷",
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.expandAllVolumes(); showVolumeMenu = false
|
viewModel.expandAllVolumes(); showVolumeMenu = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("收起所有卷") },
|
text = "收起所有卷",
|
||||||
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 = 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) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,20 +594,19 @@ fun TocScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editingBookmark != null) {
|
BookmarkEditSheet(
|
||||||
BookmarkEditSheet(
|
show = editingBookmark != null,
|
||||||
bookmark = editingBookmark!!,
|
bookmark = editingBookmark!!,
|
||||||
onDismiss = { editingBookmark = null },
|
onDismiss = { editingBookmark = null },
|
||||||
onSave = { updatedBookmark ->
|
onSave = { updatedBookmark ->
|
||||||
viewModel.updateBookmark(updatedBookmark)
|
viewModel.updateBookmark(updatedBookmark)
|
||||||
editingBookmark = null
|
editingBookmark = null
|
||||||
},
|
},
|
||||||
onDelete = { bookmarkToDelete ->
|
onDelete = { bookmarkToDelete ->
|
||||||
viewModel.deleteBookmark(bookmarkToDelete)
|
viewModel.deleteBookmark(bookmarkToDelete)
|
||||||
editingBookmark = null
|
editingBookmark = null
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| < | |||||||