diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4e6bf0320..c9c359acb 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -55,7 +55,16 @@ "PowerShell(.\\\\gradlew.bat :app:compileAppDebugKotlin 2>&1 | Select-Object -Last 40)", "PowerShell(.\\\\gradlew.bat :app:compileAppDebugKotlin 2>&1 | Select-Object -Last 100)", "PowerShell(.\\\\gradlew.bat :app:compileAppDebugKotlin 2>&1 | Select-Object -Last 50)", - "Bash(python3 *)" + "Bash(python3 *)", + "WebFetch(domain:raw.githubusercontent.com)", + "Bash(xargs -I{} jar -tf {})", + "Bash(gh api *)", + "Bash(rustup show *)", + "PowerShell(rustup show *)", + "PowerShell(npm *)", + "PowerShell(gcc *)", + "Bash(gh repo *)", + "Bash(Test-Path *)" ] } } diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index ad6611ecc..e30d0acb1 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -210,11 +210,6 @@ object PreferKey { const val secondaryTextColor = "colorMD3OnPrimaryContainer" const val themeBackgroundColor = "colorMD3Background" const val labelContainerColor = "colorMD3SurfaceContainerLow" - const val enableContainerBorder = "enableContainerBorder" - const val containerBorderWidth = "containerBorderWidth" - const val containerBorderStyle = "containerBorderStyle" - const val containerBorderColor = "containerBorderColor" - const val containerBorderDashWidth = "containerBorderDashWidth" // 中间单线间隔设置 const val enableItemDivider = "enableItemDivider" const val itemDividerWidth = "itemDividerWidth" diff --git a/app/src/main/java/io/legado/app/di/appModule.kt b/app/src/main/java/io/legado/app/di/appModule.kt index 4c035aae4..972cef6c1 100644 --- a/app/src/main/java/io/legado/app/di/appModule.kt +++ b/app/src/main/java/io/legado/app/di/appModule.kt @@ -82,6 +82,7 @@ import io.legado.app.ui.book.toc.rule.TxtTocRuleViewModel import io.legado.app.ui.config.backupConfig.BackupConfigViewModel import io.legado.app.ui.config.bookshelfConfig.BookshelfManageScreenConfig import io.legado.app.ui.config.coverConfig.CoverConfigViewModel +import io.legado.app.ui.config.downloadCacheConfig.DownloadCacheConfigViewModel import io.legado.app.ui.config.otherConfig.OtherConfigViewModel import io.legado.app.ui.config.readConfig.ReadConfigViewModel import io.legado.app.ui.config.themeConfig.ThemeConfigViewModel @@ -189,6 +190,7 @@ val appModule = module { viewModelOf(::OtherConfigViewModel) viewModelOf(::ReadConfigViewModel) viewModelOf(::CoverConfigViewModel) + viewModelOf(::DownloadCacheConfigViewModel) viewModelOf(::ThemeConfigViewModel) viewModelOf(::BackupConfigViewModel) viewModelOf(::TocViewModel) diff --git a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt index 217246ada..a36e95592 100644 --- a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt +++ b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt @@ -52,16 +52,12 @@ val cookieJar by lazy { } /** - * 强制缓存拦截器,对于图片资源,如果没有缓存头,则强制缓存30天 + * 强制缓存拦截器,对于封面请求(由CoverFetcher标记),强制缓存30天 */ private val cacheControlInterceptor = Interceptor { chain -> val request = chain.request() val response = chain.proceed(request) - val url = request.url.toString() - if (url.contains("image", true) || url.endsWith(".jpg") || url.endsWith(".png") || url.endsWith( - ".webp" - ) || url.endsWith(".jpeg") - ) { + if (request.tag() === io.legado.app.help.coil.CoverFetcher.COVER_REQUEST_TAG) { response.newBuilder() .header("Cache-Control", "public, max-age=2592000") .removeHeader("Pragma") @@ -149,6 +145,7 @@ val okHttpClient: OkHttpClient by lazy { val okHttpClientManga by lazy { okHttpClient.newBuilder().run { + cache(Cache(File(appCtx.cacheDir, "manga_cache"), 100L * 1024L * 1024L)) val interceptors = interceptors() interceptors.add(1) { chain -> val request = chain.request() @@ -167,6 +164,24 @@ val okHttpClientManga by lazy { } } +enum class HttpCacheType(val dirName: String, val maxSize: Long) { + COVER("http_cache", 100L * 1024 * 1024), + MANGA("manga_cache", 100L * 1024 * 1024), +} + +fun getHttpCacheSize(type: HttpCacheType): Long { + val dir = File(appCtx.cacheDir, type.dirName) + if (!dir.exists()) return 0 + return dir.walkTopDown().filter { it.isFile }.sumOf { it.length() } +} + +fun clearHttpCache(type: HttpCacheType) { + when (type) { + HttpCacheType.COVER -> okHttpClient.cache?.delete() + HttpCacheType.MANGA -> okHttpClientManga.cache?.delete() + } +} + /** * 缓存代理okHttp */ diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfig.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfig.kt index 847d29c30..c1a36d1c0 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfig.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfig.kt @@ -1,7 +1,7 @@ package io.legado.app.ui.config.otherConfig -import io.legado.app.BuildConfig import io.legado.app.constant.PreferKey +import io.legado.app.ui.config.downloadCacheConfig.DownloadCacheConfig import io.legado.app.ui.config.prefDelegate object OtherConfig { @@ -56,21 +56,6 @@ object OtherConfig { false ) - var bitmapCacheSize by prefDelegate( - PreferKey.bitmapCacheSize, - 50 - ) - - var imageRetainNum by prefDelegate( - PreferKey.imageRetainNum, - 0 - ) - - var preDownloadNum by prefDelegate( - PreferKey.preDownloadNum, - 10 - ) - var replaceEnableDefault by prefDelegate( PreferKey.replaceEnableDefault, true @@ -106,6 +91,18 @@ object OtherConfig { true ) + var userAgent: String + get() = DownloadCacheConfig.userAgent + set(value) { + DownloadCacheConfig.userAgent = value + } + + var cronetEnable: Boolean + get() = DownloadCacheConfig.cronetEnable + set(value) { + DownloadCacheConfig.cronetEnable = value + } + var sharedElementEnterTransitionEnable by prefDelegate( PreferKey.sharedElementEnterTransitionEnable, false @@ -116,19 +113,6 @@ object OtherConfig { true ) - private var _userAgent by prefDelegate( - PreferKey.userAgent, - "" - ) - - var userAgent: String - get() = _userAgent.ifBlank { - defaultUserAgent - } - set(value) { - _userAgent = value - } - var webServiceWakeLock by prefDelegate( PreferKey.webServiceWakeLock, false @@ -145,25 +129,40 @@ object OtherConfig { _sourceEditMaxLine = value } - var cronetEnable by prefDelegate( - PreferKey.cronet, - false - ) - var webPort by prefDelegate( PreferKey.webPort, 1122 ) - var threadCount by prefDelegate( - PreferKey.threadCount, - 16 - ) + var threadCount: Int + get() = DownloadCacheConfig.threadCount + set(value) { + DownloadCacheConfig.threadCount = value + } - var cacheBookThreadCount by prefDelegate( - PreferKey.cacheBookThreadCount, - 16 - ) + var cacheBookThreadCount: Int + get() = DownloadCacheConfig.cacheBookThreadCount + set(value) { + DownloadCacheConfig.cacheBookThreadCount = value + } + + var preDownloadNum: Int + get() = DownloadCacheConfig.preDownloadNum + set(value) { + DownloadCacheConfig.preDownloadNum = value + } + + var bitmapCacheSize: Int + get() = DownloadCacheConfig.bitmapCacheSize + set(value) { + DownloadCacheConfig.bitmapCacheSize = value + } + + var imageRetainNum: Int + get() = DownloadCacheConfig.imageRetainNum + set(value) { + DownloadCacheConfig.imageRetainNum = value + } var processText by prefDelegate( PreferKey.processText, @@ -180,9 +179,4 @@ object OtherConfig { false ) - private val defaultUserAgent: String - get() = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) " + - "Chrome/${BuildConfig.Cronet_Main_Version} Safari/537.36" - } diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt index 81a6ea858..5c083a460 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R -import io.legado.app.model.CacheBook import io.legado.app.service.WebService import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.adaptiveContentPadding @@ -34,7 +33,6 @@ import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem import io.legado.app.ui.widget.components.settingItem.InputSettingItem -import io.legado.app.ui.widget.components.settingItem.SliderSettingItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults @@ -58,8 +56,6 @@ fun OtherConfigScreen( val scrollBehavior = GlassTopAppBarDefaults.defaultScrollBehavior() - var showClearCacheDialog by remember { mutableStateOf(false) } - var showShrinkDbDialog by remember { mutableStateOf(false) } var showClearWebViewDialog by remember { mutableStateOf(false) } var showPasswordDialog by remember { mutableStateOf(false) } var showCheckSourceSheet by remember { mutableStateOf(false) } @@ -194,44 +190,6 @@ fun OtherConfigScreen( onCheckedChange = { OtherConfig.antiAlias = it } ) - SliderSettingItem( - title = stringResource(R.string.bitmap_cache_size), - description = stringResource( - R.string.bitmap_cache_size_summary, - OtherConfig.bitmapCacheSize - ), - value = OtherConfig.bitmapCacheSize.toFloat(), - defaultValue = 32f, - valueRange = 1f..2047f, - onValueChange = { - viewModel.updateBitmapCacheSize(it.toInt()) - } - ) - - SliderSettingItem( - title = stringResource(R.string.image_retain_number), - description = stringResource( - R.string.image_retain_number_summary, - OtherConfig.imageRetainNum - ), - value = OtherConfig.imageRetainNum.toFloat(), - defaultValue = 10f, - valueRange = 0f..100f, - onValueChange = { OtherConfig.imageRetainNum = it.toInt() } - ) - - SliderSettingItem( - title = stringResource(R.string.pre_download), - description = stringResource( - R.string.pre_download_s, - OtherConfig.preDownloadNum - ), - value = OtherConfig.preDownloadNum.toFloat(), - defaultValue = 10f, - valueRange = 0f..100f, - onValueChange = { OtherConfig.preDownloadNum = it.toInt() } - ) - SwitchSettingItem( title = stringResource(R.string.replace_enable_default_t), description = stringResource(R.string.replace_enable_default_s), @@ -297,12 +255,6 @@ fun OtherConfigScreen( onCheckedChange = { OtherConfig.delayBookLoadEnable = it } ) - InputSettingItem( - title = stringResource(R.string.user_agent), - value = OtherConfig.userAgent, - onConfirm = { viewModel.saveUserAgent(it) } - ) - SwitchSettingItem( title = stringResource(R.string.web_service_wake_lock), description = stringResource(R.string.web_service_wake_lock_summary), @@ -328,13 +280,6 @@ fun OtherConfigScreen( onClick = { showDirectLinkUploadSheet = true } ) - SwitchSettingItem( - title = "Cronet", - description = stringResource(R.string.pref_cronet_summary), - checked = OtherConfig.cronetEnable, - onCheckedChange = { OtherConfig.cronetEnable = it } - ) - InputSettingItem( title = stringResource(R.string.web_port_title), value = OtherConfig.webPort.toString(), @@ -347,47 +292,12 @@ fun OtherConfigScreen( } ) - ClickableSettingItem( - title = stringResource(R.string.clear_cache), - description = stringResource(R.string.clear_cache_summary), - onClick = { showClearCacheDialog = true } - ) - ClickableSettingItem( title = stringResource(R.string.clear_webview_data), description = stringResource(R.string.clear_webview_data_summary), onClick = { showClearWebViewDialog = true } ) - ClickableSettingItem( - title = stringResource(R.string.shrink_database), - description = stringResource(R.string.shrink_database_summary), - onClick = { showShrinkDbDialog = true } - ) - - SliderSettingItem( - title = stringResource(R.string.threads_num_title), - description = stringResource(R.string.threads_num_summary), - value = OtherConfig.threadCount.toFloat(), - defaultValue = 8f, - valueRange = 1f..256f, - onValueChange = { OtherConfig.threadCount = it.toInt() } - ) - - SliderSettingItem( - title = stringResource(R.string.cache_book_threads_num_title), - description = stringResource(R.string.cache_book_threads_num_summary), - value = OtherConfig.cacheBookThreadCount - .coerceIn(1, CacheBook.maxDownloadConcurrency) - .toFloat(), - defaultValue = CacheBook.maxDownloadConcurrency.toFloat(), - valueRange = 1f..CacheBook.maxDownloadConcurrency.toFloat(), - onValueChange = { - OtherConfig.cacheBookThreadCount = - it.toInt().coerceIn(1, CacheBook.maxDownloadConcurrency) - } - ) - SwitchSettingItem( title = stringResource(R.string.add_to_text_context_menu_t), description = stringResource(R.string.add_to_text_context_menu_s), @@ -437,30 +347,6 @@ fun OtherConfigScreen( onDismiss = { showDirectLinkUploadSheet = false } ) - AppAlertDialog( - show = showClearCacheDialog, - onDismissRequest = { showClearCacheDialog = false }, - title = stringResource(R.string.clear_cache), - text = stringResource(R.string.sure_del), - onConfirm = { - viewModel.clearCache(context) - showClearCacheDialog = false - }, - onDismiss = { showClearCacheDialog = false } - ) - - AppAlertDialog( - show = showShrinkDbDialog, - onDismissRequest = { showShrinkDbDialog = false }, - title = stringResource(R.string.shrink_database), - text = stringResource(R.string.sure), - onConfirm = { - viewModel.shrinkDatabase() - showShrinkDbDialog = false - }, - onDismiss = { showShrinkDbDialog = false } - ) - AppAlertDialog( show = showClearWebViewDialog, onDismissRequest = { showClearWebViewDialog = false }, diff --git a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigViewModel.kt b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigViewModel.kt index 69d9f0643..29a46ebb8 100644 --- a/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/config/otherConfig/OtherConfigViewModel.kt @@ -9,14 +9,12 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import io.legado.app.constant.PreferKey -import io.legado.app.domain.usecase.ClearBookCacheUseCase -import io.legado.app.domain.usecase.ShrinkDatabaseUseCase import io.legado.app.help.DirectLinkUpload import io.legado.app.help.config.AppConfig import io.legado.app.help.config.LocalConfig import io.legado.app.model.CheckSource -import io.legado.app.model.ImageProvider import io.legado.app.receiver.SharedReceiverActivity +import io.legado.app.ui.config.downloadCacheConfig.DownloadCacheConfig import io.legado.app.utils.FileUtils import io.legado.app.utils.putPrefString import io.legado.app.utils.restart @@ -25,10 +23,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import splitties.init.appCtx -class OtherConfigViewModel( - private val clearBookCacheUseCase: ClearBookCacheUseCase, - private val shrinkDatabaseUseCase: ShrinkDatabaseUseCase -) : ViewModel() { +class OtherConfigViewModel : ViewModel() { private val packageManager = appCtx.packageManager private val componentName = ComponentName( @@ -53,21 +48,6 @@ class OtherConfigViewModel( ) } - fun clearCache(context: Context) { - viewModelScope.launch(Dispatchers.IO) { - clearBookCacheUseCase.executeAll() - FileUtils.delete(context.cacheDir.absolutePath) - context.externalCacheDir?.deleteRecursively() - context.cacheDir.deleteRecursively() - } - } - - fun shrinkDatabase() { - viewModelScope.launch(Dispatchers.IO) { - shrinkDatabaseUseCase.execute() - } - } - fun clearWebViewData(context: Context) { viewModelScope.launch(Dispatchers.IO) { FileUtils.delete(context.getDir("webview", Context.MODE_PRIVATE)) @@ -82,13 +62,8 @@ class OtherConfigViewModel( } fun saveUserAgent(input: String) { - OtherConfig.userAgent = input - AppConfig.userAgent = OtherConfig.userAgent - } - - fun updateBitmapCacheSize(size: Int) { - AppConfig.bitmapCacheSize = size - ImageProvider.bitmapLruCache.resize(ImageProvider.cacheSize) + DownloadCacheConfig.userAgent = input + AppConfig.userAgent = DownloadCacheConfig.userAgent } fun updateLocalBookDir(path: String) { diff --git a/app/src/main/java/io/legado/app/ui/config/personalizationConfig/FontSelectScreen.kt b/app/src/main/java/io/legado/app/ui/config/personalizationConfig/FontSelectScreen.kt deleted file mode 100644 index 63a248a88..000000000 --- a/app/src/main/java/io/legado/app/ui/config/personalizationConfig/FontSelectScreen.kt +++ /dev/null @@ -1,185 +0,0 @@ -package io.legado.app.ui.config.personalizationConfig - -import android.content.Intent -import android.graphics.Typeface -import android.net.Uri -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items -import androidx.compose.material3.Button -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.res.ResourcesCompat -import io.legado.app.R -import io.legado.app.constant.PreferKey -import io.legado.app.help.loadFontFiles -import io.legado.app.ui.config.themeConfig.ThemeConfig -import io.legado.app.ui.theme.adaptiveContentPadding -import io.legado.app.ui.widget.components.AppScaffold -import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton -import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults -import io.legado.app.utils.FileDoc -import io.legado.app.utils.getPrefString -import io.legado.app.utils.putPrefString -import io.legado.app.utils.takePersistablePermissionSafely - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun FontSelectScreen( - onBackClick: () -> Unit -) { - val scrollBehavior = GlassTopAppBarDefaults.defaultScrollBehavior() - val context = LocalContext.current - var fontItems by remember { mutableStateOf>(emptyList()) } - var selectedFolderUri by remember { mutableStateOf(null) } - - // 加载字体文件 - fun loadFonts() { - fontItems = loadFontFiles(context, selectedFolderUri) - } - - // 从偏好设置中加载保存的字体文件夹路径 - remember { - val savedFontPath = context.getPrefString(PreferKey.fontFolder) - if (!savedFontPath.isNullOrEmpty()) { - selectedFolderUri = Uri.parse(savedFontPath) - } - loadFonts() - } - - // 文件夹选择启动器 - val selectFolderLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocumentTree() - ) { uri -> - if (uri != null) { - selectedFolderUri = uri - // 获取持久化权限 - uri.takePersistablePermissionSafely(context, Intent.FLAG_GRANT_READ_URI_PERMISSION) - // 保存选择的文件夹路径到偏好设置 - context.putPrefString(PreferKey.fontFolder, uri.toString()) - loadFonts() - } - } - - AppScaffold( - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - GlassMediumFlexibleTopAppBar( - title = stringResource(R.string.font_setting), - scrollBehavior = scrollBehavior, - navigationIcon = { - TopBarNavigationButton(onClick = onBackClick) - } - ) - } - ) { paddingValues -> - if (fontItems.isEmpty()) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = "没有字体文件", - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.padding(bottom = 16.dp) - ) - Button(onClick = { selectFolderLauncher.launch(null) }) { - Text(text = stringResource(R.string.select_font)) - } - } - } - } else { - LazyVerticalGrid( - columns = GridCells.Fixed(2), - modifier = Modifier.fillMaxSize(), - contentPadding = adaptiveContentPadding( - top = paddingValues.calculateTopPadding(), - bottom = 120.dp - ), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(fontItems) { - FontItem(it) { - // 选择字体的逻辑 - ThemeConfig.appFontPath = it.uri.toString() - } - } - } - } - } -} - -@Composable -fun FontItem(fontDoc: FileDoc, onFontSelected: (FileDoc) -> Unit) { - val context = LocalContext.current - - Card( - modifier = Modifier.fillMaxWidth().height(120.dp), - onClick = { - onFontSelected(fontDoc) - }, - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant - ) - ) { - // 使用AndroidView显示使用对应字体的文本 - AndroidView( - factory = { ctx -> - android.widget.TextView(ctx).apply { - text = fontDoc.name - textSize = 16f - // 设置垂直和水平居中 - gravity = android.view.Gravity.CENTER - // 设置最大行数为2,超过省略 - maxLines = 2 - ellipsize = android.text.TextUtils.TruncateAt.END - // 加载并设置字体 - runCatching { - val typeface: Typeface? = if (fontDoc.uri.scheme == "content") { - ctx.contentResolver.openFileDescriptor(fontDoc.uri, "r")?.use { - Typeface.Builder(it.fileDescriptor).build() - } - } else { - Typeface.createFromFile(fontDoc.uri.path!!) - } - this.typeface = typeface - }.onFailure { - // 字体加载失败,使用默认字体 - } - } - }, - modifier = Modifier.fillMaxSize() - ) - } -} - diff --git a/app/src/main/java/io/legado/app/ui/config/themeManage/EditThemeSheet.kt b/app/src/main/java/io/legado/app/ui/config/themeManage/EditThemeSheet.kt index 0e54bf998..fdf99a707 100644 --- a/app/src/main/java/io/legado/app/ui/config/themeManage/EditThemeSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/themeManage/EditThemeSheet.kt @@ -276,11 +276,6 @@ fun EditThemeSheet( valueRange = 0f..100f, onValueChange = { data = data.copy(containerOpacity = it.toInt()) } ) - CompactSwitchSettingItem( - title = "容器边框", - checked = data.enableContainerBorder, - onCheckedChange = { data = data.copy(enableContainerBorder = it) } - ) Spacer(modifier = Modifier.height(8.dp)) diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index f31904420..b20d34050 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -62,9 +62,9 @@ import io.legado.app.ui.config.ConfigNavScreen import io.legado.app.ui.config.ConfigTag import io.legado.app.ui.config.backupConfig.BackupConfigScreen import io.legado.app.ui.config.coverConfig.CoverConfigScreen +import io.legado.app.ui.config.downloadCacheConfig.DownloadCacheConfigScreen import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.otherConfig.OtherConfigScreen -import io.legado.app.ui.config.personalizationConfig.FontSelectScreen import io.legado.app.ui.config.customTheme.CustomThemeScreen import io.legado.app.ui.config.readConfig.ReadConfigScreen import io.legado.app.ui.config.themeConfig.ThemeConfigScreen @@ -105,6 +105,7 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { private const val ROUTE_SETTINGS_THEME = "settings/theme" private const val ROUTE_SETTINGS_BACKUP = "settings/backup" private const val ROUTE_SETTINGS_CUSTOM_THEME = "settings/custom_theme" + private const val ROUTE_SETTINGS_DOWNLOAD_CACHE = "settings/download_cache" private const val ROUTE_IMPORT_LOCAL = "import/local" private const val ROUTE_IMPORT_REMOTE = "import/remote" private const val ROUTE_CACHE = "cache" @@ -255,6 +256,7 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { ConfigTag.COVER_CONFIG -> ROUTE_SETTINGS_COVER ConfigTag.THEME_CONFIG -> ROUTE_SETTINGS_THEME ConfigTag.BACKUP_CONFIG -> ROUTE_SETTINGS_BACKUP + ConfigTag.DOWNLOAD_CACHE_CONFIG -> ROUTE_SETTINGS_DOWNLOAD_CACHE else -> ROUTE_SETTINGS } } @@ -294,6 +296,9 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { @Serializable private data object MainRouteSettingsThemeManage : MainRoute + @Serializable + private data object MainRouteSettingsDownloadCache : MainRoute + @Serializable private data object MainRouteImportLocal : MainRoute @@ -551,7 +556,8 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { onNavigateToRead = { backStack.add(MainRouteSettingsRead) }, onNavigateToCover = { backStack.add(MainRouteSettingsCover) }, onNavigateToTheme = { backStack.add(MainRouteSettingsTheme) }, - onNavigateToBackup = { backStack.add(MainRouteSettingsBackup) } + onNavigateToBackup = { backStack.add(MainRouteSettingsBackup) }, + onNavigateToDownloadCache = { backStack.add(MainRouteSettingsDownloadCache) } ) } @@ -579,6 +585,10 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { BackupConfigScreen(onBackClick = { navigateBack(backStack) }) } + entry { + DownloadCacheConfigScreen(onBackClick = { navigateBack(backStack) }) + } + entry { CustomThemeScreen( onBackClick = { navigateBack(backStack) } @@ -832,7 +842,8 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { MainRouteSettingsTheme, MainRouteSettingsBackup, MainRouteSettingsCustomTheme, - MainRouteSettingsThemeManage -> { + MainRouteSettingsThemeManage, + MainRouteSettingsDownloadCache -> { backStack.clear() backStack.add(MainRouteHome) backStack.add(MainRouteSettings) @@ -1095,6 +1106,7 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { "settings/theme" -> MainRouteSettingsTheme "settings/backup" -> MainRouteSettingsBackup "settings/custom_theme" -> MainRouteSettingsCustomTheme + "settings/download_cache" -> MainRouteSettingsDownloadCache "import/local" -> MainRouteImportLocal "import/remote" -> MainRouteImportRemote ROUTE_MAIN -> MainRouteHome @@ -1104,6 +1116,7 @@ open class MainActivity : BaseComposeActivity(), VariableDialog.Callback { ROUTE_SETTINGS_COVER -> MainRouteSettingsCover ROUTE_SETTINGS_THEME -> MainRouteSettingsTheme ROUTE_SETTINGS_BACKUP -> MainRouteSettingsBackup + ROUTE_SETTINGS_DOWNLOAD_CACHE -> MainRouteSettingsDownloadCache ROUTE_IMPORT_LOCAL -> MainRouteImportLocal ROUTE_IMPORT_REMOTE -> MainRouteImportRemote ROUTE_CACHE -> MainRouteCache(intent?.getLongExtra(EXTRA_CACHE_GROUP_ID, -1L) ?: -1L) diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt index fab9dbb6f..0ed096f4b 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -285,22 +284,12 @@ fun ExploreScreen( .align(Alignment.TopStart) .padding(top = paddingValues.calculateTopPadding() + 4.dp, start = 8.dp) ) { item -> - val enableBorder = ThemeConfig.enableDeepPersonalization && ThemeConfig.enableContainerBorder - val borderWidth = ThemeConfig.containerBorderWidth.dp - val borderColor = if (ThemeConfig.containerBorderColor != 0) { - Color(ThemeConfig.containerBorderColor) - } else { - LegadoTheme.colorScheme.outline - } TextCard( text = item.bookSourceName, textStyle = LegadoTheme.typography.labelMediumEmphasized, cornerRadius = 12.dp, horizontalPadding = 12.dp, verticalPadding = 8.dp, - border = if (enableBorder) { - BorderStroke(borderWidth, borderColor) - } else null, onClick = { scope.launch { val index = @@ -371,23 +360,12 @@ fun ExploreSourceHeader( label = "CardColor" ) - val enableBorder = ThemeConfig.enableDeepPersonalization && ThemeConfig.enableContainerBorder - val borderWidth = ThemeConfig.containerBorderWidth.dp - val borderColor = if (ThemeConfig.containerBorderColor != 0) { - Color(ThemeConfig.containerBorderColor) - } else { - LegadoTheme.colorScheme.outline - } - GlassCard( modifier = modifier .fillMaxWidth() .padding(vertical = 4.dp), cornerRadius = 12.dp, containerColor = containerColor, - border = if (enableBorder) { - BorderStroke(borderWidth, borderColor) - } else null ) { ListItem( modifier = Modifier diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 34fb9a776..842bd9506 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1483,4 +1483,12 @@ · 进度 %1$d/%2$d %1$s分组搜索结果为空,是否关闭精准搜索? %1$s分组搜索结果为空,是否切换到全部分组? + 下载与缓存 + HTTP缓存 + 封面缓存 + 漫画缓存 + %1$.1f MB + 下载 + 图片缓存 + 网络 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index acace5f86..0081b0aaa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1527,4 +1527,12 @@ · Progress %1$d/%2$d %1$s group search returned no results. Disable precise search? %1$s group search returned no results. Switch to all groups? + Download & Cache + HTTP Cache + Cover Cache + Manga Cache + %1$.1f MB + Download + Image Cache + Network