[优化] 优化界面
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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()) }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -304,6 +304,7 @@ fun RemoteBookScreen(
|
||||
)
|
||||
},
|
||||
selectionActions = SelectionActions(
|
||||
onClearSelection = { viewModel.clearSelection() },
|
||||
onSelectAll = { viewModel.dispatch(RemoteBookIntent.SelectAll) },
|
||||
onSelectInvert = { viewModel.dispatch(RemoteBookIntent.SelectInvert) },
|
||||
primaryAction = ActionItem(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
bodySmallEmphasized = miuixStyles.body2.copy(
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
),
|
||||
|
||||
labelLargeEmphasized = miuixStyles.button.copy(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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -101,6 +101,7 @@ fun <T> RuleListScaffold(
|
||||
floatingActionButton = floatingActionButton,
|
||||
snackbarHostState = snackbarHostState,
|
||||
selectionActions = SelectionActions(
|
||||
onClearSelection = onClearSelection,
|
||||
onSelectAll = onSelectAll,
|
||||
onSelectInvert = onSelectInvert,
|
||||
primaryAction = ActionItem(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user