Ver código fonte

[优化] 优化界面

HapeLee 7 meses atrás
pai
commit
9410e9e0b5

+ 1 - 0
app/src/main/java/io/legado/app/constant/PreferKey.kt

@@ -134,6 +134,7 @@ object PreferKey {
     const val doublePageHorizontal = "doubleHorizontalPage"
     const val readUrlOpenInBrowser = "readUrlInBrowser"
     const val defaultBookTreeUri = "defaultBookTreeUri"
+    const val importBookPath = "importBookPath"
     const val checkSource = "checkSource"
     const val uploadRule = "uploadRule"
     const val tocUiUseReplace = "tocUiUseReplace"

+ 2 - 0
app/src/main/java/io/legado/app/di/appModule.kt

@@ -15,6 +15,7 @@ import io.legado.app.data.repository.ReadRecordRepository
 import io.legado.app.data.repository.RemoteBookRepository
 import io.legado.app.data.repository.SearchContentRepository
 import io.legado.app.data.repository.UploadRepository
+import io.legado.app.domain.usecase.ExploreKindUiUseCase
 import io.legado.app.help.coil.CoverFetcher
 import io.legado.app.help.coil.CoverInterceptor
 import io.legado.app.help.http.okHttpClient
@@ -64,6 +65,7 @@ val appModule = module {
     singleOf(::BookGroupRepository)
     singleOf(::SearchContentRepository)
     singleOf(::RemoteBookRepository)
+    singleOf(::ExploreKindUiUseCase)
 
     single<UploadRepository> { DirectLinkUploadRepository() }
     single<ExploreRepository> { ExploreRepositoryImpl(get()) }

+ 15 - 1
app/src/main/java/io/legado/app/help/source/BookSourceExtensions.kt

@@ -1,6 +1,7 @@
 package io.legado.app.help.source
 
 import com.script.rhino.runScriptWithContext
+import androidx.collection.LruCache
 import io.legado.app.constant.BookSourceType
 import io.legado.app.constant.BookType
 import io.legado.app.data.entities.BookSource
@@ -8,6 +9,7 @@ import io.legado.app.data.entities.BookSourcePart
 import io.legado.app.data.entities.rule.ExploreKind
 import io.legado.app.utils.ACache
 import io.legado.app.utils.GSON
+import io.legado.app.utils.InfoMap
 import io.legado.app.utils.MD5Utils
 import io.legado.app.utils.fromJsonArray
 import io.legado.app.utils.isJsonArray
@@ -25,6 +27,15 @@ import java.util.concurrent.ConcurrentHashMap
 private val mutexMap by lazy { hashMapOf<String, Mutex>() }
 private val exploreKindsMap by lazy { ConcurrentHashMap<String, List<ExploreKind>>() }
 private val aCache by lazy { ACache.get("explore") }
+private val exploreInfoMapList by lazy { LruCache<String, InfoMap>(99) }
+
+fun getExploreInfoMap(sourceUrl: String): InfoMap {
+    return synchronized(exploreInfoMapList) {
+        exploreInfoMapList[sourceUrl] ?: InfoMap(sourceUrl).also {
+            exploreInfoMapList.put(sourceUrl, it)
+        }
+    }
+}
 
 private fun BookSource.getExploreKindsKey(): String {
     return MD5Utils.md5Encode(bookSourceUrl + exploreUrl)
@@ -57,13 +68,16 @@ suspend fun BookSource.exploreKinds(): List<ExploreKind> {
                 ) {
                     ruleStr = aCache.getAsString(exploreKindsKey)
                     if (ruleStr.isNullOrBlank()) {
+                        val exploreInfoMap = getExploreInfoMap(bookSourceUrl)
                         val jsStr = if (exploreUrl.startsWith("@")) {
                             exploreUrl.substring(4)
                         } else {
                             exploreUrl.substring(4, exploreUrl.lastIndexOf("<"))
                         }
                         ruleStr = runScriptWithContext {
-                            evalJS(jsStr).toString().trim()
+                            evalJS(jsStr) {
+                                put("infoMap", exploreInfoMap)
+                            }.toString().trim()
                         }
                         aCache.put(exploreKindsKey, ruleStr)
                     }

+ 1 - 0
app/src/main/java/io/legado/app/ui/book/import/remote/RemoteBookScreen.kt

@@ -304,6 +304,7 @@ fun RemoteBookScreen(
             )
         },
         selectionActions = SelectionActions(
+            onClearSelection = { viewModel.clearSelection() },
             onSelectAll = { viewModel.dispatch(RemoteBookIntent.SelectAll) },
             onSelectInvert = { viewModel.dispatch(RemoteBookIntent.SelectInvert) },
             primaryAction = ActionItem(

+ 5 - 2
app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt

@@ -845,11 +845,14 @@ private fun BookInfoSummary(
         ) {
             AppText(
                 text = stringResource(R.string.read_chapter_total, book.totalChapterNum),
-                style = LegadoTheme.typography.bodyMedium,
+                style = LegadoTheme.typography.labelMedium,
                 color = LegadoTheme.colorScheme.primary,
                 fontWeight = FontWeight.Bold,
             )
-            AppText(text = "|", color = LegadoTheme.colorScheme.secondary)
+            AppText(
+                text = "|",
+                color = LegadoTheme.colorScheme.secondary
+            )
             AppText(
                 text = if (book.durChapterIndex + 1 == book.totalChapterNum && book.totalChapterNum > 0) "已读完" else stringResource(R.string.read_chapter_index, book.durChapterIndex + 1),
                 style = LegadoTheme.typography.labelMedium,

+ 1 - 37
app/src/main/java/io/legado/app/ui/theme/AppTheme.kt

@@ -13,8 +13,6 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontWeight
 import io.legado.app.ui.config.themeConfig.ThemeConfig
 import top.yukonga.miuix.kmp.theme.MiuixTheme
 import top.yukonga.miuix.kmp.theme.ThemeController
@@ -132,37 +130,7 @@ fun AppTheme(
             MiuixTheme(controller = controller) {
                 val miuixStyles = MiuixTheme.textStyles
                 val legadoTypography = remember(miuixStyles) {
-                    LegadoTypography(
-                        headlineLarge = miuixStyles.title1,
-                        headlineLargeEmphasized = miuixStyles.title1.emphasized(),
-                        headlineMedium = miuixStyles.title2,
-                        headlineMediumEmphasized = miuixStyles.title2.emphasized(),
-                        headlineSmall = miuixStyles.title3,
-                        headlineSmallEmphasized = miuixStyles.title3.emphasized(),
-
-
-                        titleLarge = miuixStyles.headline1,
-                        titleLargeEmphasized = miuixStyles.headline1.emphasized(),
-                        titleMedium = miuixStyles.headline2,
-                        titleMediumEmphasized = miuixStyles.headline2.emphasized(),
-                        titleSmall = miuixStyles.subtitle,
-                        titleSmallEmphasized = miuixStyles.subtitle.emphasized(),
-
-
-                        bodyLarge = miuixStyles.paragraph,
-                        bodyLargeEmphasized = miuixStyles.paragraph.emphasized(),
-                        bodyMedium = miuixStyles.body1,
-                        bodyMediumEmphasized = miuixStyles.body1.emphasized(),
-                        bodySmall = miuixStyles.body2,
-                        bodySmallEmphasized = miuixStyles.body2.emphasized(),
-
-                        labelLarge = miuixStyles.button,
-                        labelLargeEmphasized = miuixStyles.button.emphasized(),
-                        labelMedium = miuixStyles.footnote1,
-                        labelMediumEmphasized = miuixStyles.footnote1.emphasized(),
-                        labelSmall = miuixStyles.footnote2,
-                        labelSmallEmphasized = miuixStyles.footnote2.emphasized()
-                    )
+                    miuixStylesToM3Typography(miuixStyles).toLegadoTypography()
                 }
 
                 val miuixColorScheme = MiuixTheme.colorScheme
@@ -290,7 +258,3 @@ private fun Typography.toLegadoTypography(): LegadoTypography {
         labelSmallEmphasized = labelSmallEmphasized
     )
 }
-
-private fun TextStyle.emphasized(): TextStyle {
-    return copy(fontWeight = FontWeight.Medium)
-}

+ 19 - 12
app/src/main/java/io/legado/app/ui/theme/Typography.kt

@@ -3,6 +3,7 @@ package io.legado.app.ui.theme
 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Typography
 import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
 import top.yukonga.miuix.kmp.theme.TextStyles
 
 
@@ -17,28 +18,34 @@ fun miuixStylesToM3Typography(miuixStyles: TextStyles): Typography {
         displayMedium = miuixStyles.title2,  // 24.sp
         displaySmall = miuixStyles.title3,   // 20.sp
 
-        headlineLarge = miuixStyles.title2,  // 24.sp
-        headlineMedium = miuixStyles.title3, // 20.sp
-        headlineSmall = miuixStyles.title4,  // 18.sp
+        headlineLarge = miuixStyles.title1,  // 32.sp
+        headlineMedium = miuixStyles.title2, // 24.sp
+        headlineSmall = miuixStyles.title3,  // 20.sp
 
-        titleLarge = miuixStyles.headline1,  // 17.sp
+        titleLarge = miuixStyles.title4,     // 18.sp
         titleMedium = miuixStyles.headline2, // 16.sp
         titleSmall = miuixStyles.subtitle,   // 14.sp, Bold
 
-        bodyLarge = miuixStyles.paragraph,   // 17.sp, lineHeight 1.2em (如果不需要行高也可以换成 main)
+        bodyLarge = miuixStyles.paragraph,   // 17.sp
         bodyMedium = miuixStyles.body1,      // 16.sp
-        bodySmall = miuixStyles.body2,       // 14.sp
+        bodySmall = miuixStyles.body2.copy(fontSize = 12.sp), // 12.sp
 
-        labelLarge = miuixStyles.button,     // 17.sp
+        labelLarge = miuixStyles.footnote1.copy(fontSize = 14.sp), // 14.sp
         labelMedium = miuixStyles.footnote1, // 13.sp
-        labelSmall = miuixStyles.footnote2,   // 11.sp
+        labelSmall = miuixStyles.footnote2,  // 11.sp
 
         bodyLargeEmphasized = miuixStyles.paragraph.copy(fontWeight = FontWeight.Medium),
         bodyMediumEmphasized = miuixStyles.body1.copy(fontWeight = FontWeight.Medium),
-        bodySmallEmphasized = miuixStyles.body2.copy(fontWeight = FontWeight.Medium),
-
-        labelLargeEmphasized = miuixStyles.button.copy(fontWeight = FontWeight.Medium),
+        bodySmallEmphasized = miuixStyles.body2.copy(
+            fontSize = 12.sp,
+            fontWeight = FontWeight.Medium
+        ),
+
+        labelLargeEmphasized = miuixStyles.button.copy(
+            fontSize = 14.sp,
+            fontWeight = FontWeight.Medium
+        ),
         labelMediumEmphasized = miuixStyles.footnote1.copy(fontWeight = FontWeight.Medium),
         labelSmallEmphasized = miuixStyles.footnote2.copy(fontWeight = FontWeight.Medium)
     )
-}
+}

+ 58 - 1
app/src/main/java/io/legado/app/ui/widget/components/AppTextField.kt

@@ -3,6 +3,7 @@ package io.legado.app.ui.widget.components
 import androidx.compose.foundation.ScrollState
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
@@ -22,6 +23,7 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.input.VisualTransformation
 import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.dp
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.theme.ThemeResolver
 import io.legado.app.ui.widget.components.text.AppText
@@ -272,6 +274,61 @@ fun AppTextFieldSurface(
     )
 }
 
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun AppDenseTextField(
+    state: TextFieldState,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    readOnly: Boolean = false,
+    backgroundColor: Color = Color.Unspecified,
+    label: String? = null,
+    labelPosition: TextFieldLabelPosition = TextFieldLabelPosition.Attached(),
+    placeholder: @Composable (() -> Unit)? = null,
+    leadingIcon: @Composable (() -> Unit)? = null,
+    trailingIcon: @Composable (() -> Unit)? = null,
+    prefix: @Composable (() -> Unit)? = null,
+    suffix: @Composable (() -> Unit)? = null,
+    supportingText: @Composable (() -> Unit)? = null,
+    isError: Boolean = false,
+    inputTransformation: InputTransformation? = null,
+    outputTransformation: OutputTransformation? = null,
+    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+    onKeyboardAction: KeyboardActionHandler? = null,
+    lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default,
+    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
+    scrollState: ScrollState = rememberScrollState(),
+    shape: Shape = TextFieldDefaults.shape,
+    interactionSource: MutableInteractionSource? = null,
+) {
+    AppTextField(
+        state = state,
+        modifier = modifier.heightIn(min = 48.dp),
+        enabled = enabled,
+        readOnly = readOnly,
+        backgroundColor = backgroundColor,
+        label = label,
+        labelPosition = labelPosition,
+        placeholder = placeholder,
+        leadingIcon = leadingIcon,
+        trailingIcon = trailingIcon,
+        prefix = prefix,
+        suffix = suffix,
+        supportingText = supportingText,
+        isError = isError,
+        inputTransformation = inputTransformation,
+        outputTransformation = outputTransformation,
+        keyboardOptions = keyboardOptions,
+        onKeyboardAction = onKeyboardAction,
+        lineLimits = lineLimits,
+        onTextLayout = onTextLayout,
+        scrollState = scrollState,
+        shape = shape,
+        contentPadding = PaddingValues(top = 4.dp, bottom = 4.dp, start = 12.dp, end = 12.dp),
+        interactionSource = interactionSource
+    )
+}
+
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun AppTextFieldSurface(
@@ -321,4 +378,4 @@ fun AppTextFieldSurface(
         shape = shape,
         interactionSource = interactionSource
     )
-}
+}

+ 2 - 2
app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt

@@ -79,7 +79,7 @@ fun SearchBarSection(
         )
 
     val searchTextField = @Composable {
-        AppTextField(
+        AppDenseTextField(
             state = textFieldState,
             modifier = modifier,
             placeholder = { AppText(placeholder) },
@@ -106,4 +106,4 @@ fun SearchBarSection(
             searchTextField()
         }
     }
-}
+}

+ 2 - 1
app/src/main/java/io/legado/app/ui/widget/components/SelectionBottomBar.kt

@@ -31,6 +31,7 @@ import io.legado.app.ui.widget.components.text.AppText
 data class SelectionActions(
     val primaryAction: ActionItem,
     val secondaryActions: List<ActionItem> = emptyList(),
+    val onClearSelection: (() -> Unit)? = null,
     val onSelectAll: () -> Unit,
     val onSelectInvert: () -> Unit,
 )
@@ -113,4 +114,4 @@ fun SelectionBottomBar(
             }
         }
     )
-}
+}

+ 1 - 1
app/src/main/java/io/legado/app/ui/widget/components/list/ListScaffold.kt

@@ -88,7 +88,7 @@ fun <T> ListScaffold(
                 onSearchToggle = onSearchToggle,
                 onSearchQueryChange = onSearchQueryChange,
                 searchPlaceholder = searchPlaceholder,
-                onClearSelection = { selectionActions?.onSelectInvert?.invoke() },
+                onClearSelection = { selectionActions?.onClearSelection?.invoke() },
                 topBarActions = topBarActions,
                 dropDownMenuContent = dropDownMenuContent,
                 bottomContent = bottomContent

+ 1 - 0
app/src/main/java/io/legado/app/ui/widget/components/rules/RuleListScaffold.kt

@@ -101,6 +101,7 @@ fun <T> RuleListScaffold(
         floatingActionButton = floatingActionButton,
         snackbarHostState = snackbarHostState,
         selectionActions = SelectionActions(
+            onClearSelection = onClearSelection,
             onSelectAll = onSelectAll,
             onSelectInvert = onSelectInvert,
             primaryAction = ActionItem(

+ 7 - 0
app/src/main/java/io/legado/app/utils/UriExtensions.kt

@@ -38,6 +38,13 @@ fun Uri.takePersistablePermissionSafely(
     modeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
 ): Boolean {
     if (!isContentScheme()) return false
+    kotlin.runCatching {
+        context.contentResolver.takePersistableUriPermission(this, modeFlags)
+    }.onSuccess {
+        return true
+    }.onFailure {
+        AppLog.put("持久化读写权限失败(组合模式): $this", it)
+    }
     var granted = false
     if (modeFlags and Intent.FLAG_GRANT_READ_URI_PERMISSION != 0) {
         kotlin.runCatching {