style: address IDE warnings

Remove unused imports and an unused spacing constant, drop redundant if
checks and redundant opt-in markers, replace loop variables with
destructuring, convert a string concatenation to a template, use
Configuration.screenHeightDp instead of LocalWindowInfo.containerSize, and
opt in to ExperimentalSerializationApi for decodeFromStream.
This commit is contained in:
OneWay committed 2026-10-06 09:42:54 +08:00
1 parent e9706ab12a
commit 92fc5562db
15 files changed
+56 -76

No files matched your search

@@ -59,13 +59,12 @@ class NotificationHelper(private val context: Context) : NotificationPort {
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
manager?.createNotificationChannel(channel)
}
private fun canShowNotification(): Boolean {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU) return true
return ContextCompat.checkSelfPermission(
private fun canShowNotification(): Boolean =
android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU ||
ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.POST_NOTIFICATIONS
) == android.content.pm.PackageManager.PERMISSION_GRANTED
}
override fun showProgress(percent: Int, titleRes: Int) {
showUnifiedProgressNotification(
title = context.getString(titleRes),
@@ -454,11 +454,7 @@ class IndexSearcher(private val context: Context) {
val originalWord = readPooledString(source, source.readUnsignedShort())
val offset = ArticleOffset(source.readLong())
val length = ArticleLength(source.readInt())
val isAlias = if (metadata.version >= 6) {
source.readUnsignedByte() and ENTRY_FLAG_ALIAS != 0
} else {
false
}
val isAlias = metadata.version >= 6 && source.readUnsignedByte() and ENTRY_FLAG_ALIAS != 0
return IndexEntry(word, originalWord, offset, length, isAlias = isAlias)
}
@@ -472,8 +468,11 @@ class IndexSearcher(private val context: Context) {
private fun openSource(pathOrUri: String): RandomAccessSource {
val file = File(pathOrUri)
if (!file.exists()) throw DictionaryError.FileSystemError.NotFound(pathOrUri)
return FileSource(file)
return if (file.exists()) {
FileSource(file)
} else {
throw DictionaryError.FileSystemError.NotFound(pathOrUri)
}
}
private fun openInputStream(pathOrUri: String): java.io.InputStream {
val file = File(pathOrUri)
@@ -112,20 +112,20 @@ class KotlinDictionaryEngine(private val context: Context) : ProgressIndexingEng
maxResults: Int
): List<IndexEntry> = withContext(Dispatchers.IO) {
val allResults = mutableListOf<IndexEntry>()
for (dict in dictionaries) {
for ((name, path, indexPath, _, _, metadata) in dictionaries) {
try {
val indexPath = resolveIndexPath(dict.indexPath)
val entry = indexSearcher.findFirstEntry(indexPath, query)
val resolvedIndexPath = resolveIndexPath(indexPath)
val entry = indexSearcher.findFirstEntry(resolvedIndexPath, query)
if (entry != null) {
allResults.add(entry.withDictionary(dict.metadata.name.ifBlank { dict.name }, dict.path))
allResults.add(entry.withDictionary(metadata.name.ifBlank { name }, path))
}
if (allResults.size >= maxResults) break
} catch (e: OutOfMemoryError) {
Log.e(TAG, "search() - OOM for ${dict.indexPath}", e)
Log.e(TAG, "search() - OOM for $indexPath", e)
trimMemory(80)
break
} catch (e: Exception) {
Log.w(TAG, "search() - error for ${dict.indexPath}: ${e.message}")
Log.w(TAG, "search() - error for $indexPath: ${e.message}")
}
}
allResults
@@ -538,12 +538,12 @@ class LocalDictionaryRepository(
val dictionaries = mutableDictionaries.value
if (dictionaries.isEmpty()) return@withContext
for (dict in dictionaries) {
for ((_, _, indexPath) in dictionaries) {
try {
val indexPath = resolveIndexPath(dict.indexPath)
val resolvedIndexPath = resolveIndexPath(indexPath)
val indexSearcher = engine.getIndexSearcher()
if (!indexSearcher.isMetadataLoaded(indexPath)) {
engine.preloadIndexMetadata(indexPath)
if (!indexSearcher.isMetadataLoaded(resolvedIndexPath)) {
engine.preloadIndexMetadata(resolvedIndexPath)
}
yield()
} catch (_: Exception) { /* Ignore preload failure */ }
@@ -54,17 +54,17 @@ class DictionaryCleaner(
for ((prefix, items) in parsedByPrefix) {
val latestDsl = latestDslDateByPrefix[prefix] ?: continue
val dslDates = dslDatesByPrefix[prefix].orEmpty()
for (item in items) {
if (DateUtils.isDateBefore(item.date, latestDsl)) {
toDelete.add(item.name)
for ((name, _, date, ext) in items) {
if (DateUtils.isDateBefore(date, latestDsl)) {
toDelete.add(name)
continue
}
if (item.ext in indexExtensions && item.date != latestDsl) {
toDelete.add(item.name)
if (ext in indexExtensions && date != latestDsl) {
toDelete.add(name)
continue
}
if (item.ext in indexExtensions && item.date !in dslDates) {
toDelete.add(item.name)
if (ext in indexExtensions && date !in dslDates) {
toDelete.add(name)
}
}
}
@@ -46,14 +46,13 @@ class DictionaryExtractor(
reportProgress(processedIndex.toFloat() / totalFiles)
}
for (file in gzFiles) {
val fileName = file.name
for ((fileName, uri) in gzFiles) {
val baseName = fileName.dropLast(DictionaryConfig.GZ_EXTENSION.length)
val lowerBaseName = baseName.lowercase()
if (baseName.isBlank() ||
lowerBaseName.endsWith(DictionaryConfig.GZ_EXTENSION) ||
lowerBaseName.endsWith(".txt")) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
markFileProcessed()
continue
}
@@ -65,19 +64,19 @@ class DictionaryExtractor(
val dslFileName = "$dslBaseName${DictionaryConfig.DSL_EXTENSION}"
val existingDslFile = fileStorageManager.findFile(folderUri, dslFileName)
if (existingDslFile != null && existingDslFile.exists()) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
markFileProcessed()
continue
}
val dslUri = fileStorageManager.createFileInFolder(folderUri, dslFileName, overwrite = false)
?: continue
val extractResult = ArchiveUtils.extractGzWithBom(context, file.uri, dslUri)
val extractResult = ArchiveUtils.extractGzWithBom(context, uri, dslUri)
if (extractResult.isSuccess) {
val extractedFile = fileStorageManager.getDocumentFile(dslUri)
if (extractedFile != null && extractedFile.exists()) {
if (extractedFile.length() == 0L) {
ArchiveUtils.deleteFile(context, dslUri)
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
markFileProcessed()
continue
}
@@ -92,7 +91,7 @@ class DictionaryExtractor(
ArchiveUtils.deleteFile(context, dslUri)
}
}
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
} else {
Log.e("DictionaryExtractor", "File extraction error: $fileName")
ArchiveUtils.deleteFile(context, dslUri)
@@ -100,12 +99,11 @@ class DictionaryExtractor(
markFileProcessed()
}
for (file in rawDslFiles) {
val dslFileName = file.name
for ((dslFileName, uri) in rawDslFiles) {
val dzFileName = "$dslFileName.dz"
val existingDz = fileStorageManager.findFile(folderUri, dzFileName)
if (existingDz != null && existingDz.exists()) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
markFileProcessed()
continue
}
@@ -113,11 +111,11 @@ class DictionaryExtractor(
val fileBaseProgress = processedIndex.toFloat() / totalFiles
val fileProgressWeight = 1f / totalFiles
reportProgress(fileBaseProgress)
val compressResult = ensureDslDictZip(file.uri, dslFileName, folderUri) { compressProgress ->
val compressResult = ensureDslDictZip(uri, dslFileName, folderUri) { compressProgress ->
reportProgress(fileBaseProgress + (compressProgress * fileProgressWeight))
}
if (compressResult.isSuccess) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
}
markFileProcessed()
}
@@ -130,11 +128,10 @@ class DictionaryExtractor(
!lowerName.endsWith(DictionaryConfig.DICTZIP_EXTENSION) &&
!lowerName.endsWith(".dsl.gz")
}
for (file in remainingRawDslFiles) {
val dslFileName = file.name
val compressResult = ensureDslDictZip(file.uri, dslFileName, folderUri, onProgress = null)
for ((dslFileName, uri) in remainingRawDslFiles) {
val compressResult = ensureDslDictZip(uri, dslFileName, folderUri, onProgress = null)
if (compressResult.isSuccess) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
}
}
@@ -152,18 +149,18 @@ class DictionaryExtractor(
try {
withContext(Dispatchers.IO + NonCancellable) {
val files = fileStorageManager.listFilesInFolder(folderUri)
for (file in files) {
val n = file.name.lowercase()
for ((name, uri) in files) {
val n = name.lowercase()
val isRawDsl = n.endsWith(DictionaryConfig.DSL_EXTENSION) &&
!n.endsWith(DictionaryConfig.DICTZIP_EXTENSION) &&
!n.endsWith(".dsl.gz")
val isBareDz = n.endsWith(".dz") && !n.endsWith(DictionaryConfig.DICTZIP_EXTENSION)
when {
isBareDz -> ArchiveUtils.deleteFile(context, file.uri)
isBareDz -> ArchiveUtils.deleteFile(context, uri)
isRawDsl -> {
val pair = fileStorageManager.findFile(folderUri, file.name + ".dz")
val pair = fileStorageManager.findFile(folderUri, "$name.dz")
if (pair == null || !pair.exists()) {
ArchiveUtils.deleteFile(context, file.uri)
ArchiveUtils.deleteFile(context, uri)
}
}
}
@@ -144,9 +144,8 @@ class DictionaryRepository(
if (filesToDelete.isNotEmpty()) {
var deletedCount = 0
for (file in filesToDelete) {
val fileName = file.name
val docFile = fileStorageManager.getDocumentFile(file.uri)
for ((fileName, uri) in filesToDelete) {
val docFile = fileStorageManager.getDocumentFile(uri)
if (docFile != null && docFile.exists()) {
val deleted = docFile.delete()
if (deleted) {
@@ -2,6 +2,7 @@ package com.example.research.ui.about
import android.content.Context
import androidx.annotation.RawRes
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@@ -75,6 +76,7 @@ internal object AboutLibrariesParser {
ignoreUnknownKeys = true
}
@OptIn(ExperimentalSerializationApi::class)
fun read(context: Context, @RawRes resourceId: Int): AboutLibrariesData =
context.resources.openRawResource(resourceId)
.use { stream -> json.decodeFromStream(stream) }
@@ -5,7 +5,6 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -57,7 +56,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AboutScreen(
onNavigateBack: () -> Unit
@@ -182,7 +181,6 @@ private fun AboutHeader(versionName: String) {
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun AboutLibraryRow(
modifier: Modifier = Modifier,
@@ -19,7 +19,6 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
@@ -349,7 +348,6 @@ fun ArticleTitleBar(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun ArticleScreen(
articleState: ArticleState?,
@@ -81,15 +81,11 @@ fun MainRoute(
val showDictionaryName = remember(settingsState) {
val activeDictionaries = settingsState.dictionaries.filter { it.isActive }
if (activeDictionaries.isEmpty()) {
false
} else {
activeDictionaries.any { dict ->
val fileName = dict.path.substringAfterLast("/")
!DictionaryConfig.isDabkrsDictionary(fileName)
}
}
}
BoxWithConstraints {
val isWide = maxWidth >= 600.dp
@@ -4,7 +4,6 @@ package com.example.research.ui.main.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
@@ -17,7 +16,6 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
@@ -72,6 +70,7 @@ import com.example.research.ui.theme.Spacing
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
import kotlin.time.Duration.Companion.milliseconds
private val TopBarHeight = Spacing.topBarHeight
private val TopBarShape = RoundedCornerShape(28.dp)
@@ -150,7 +149,7 @@ fun MainTopBar(
onShowHistory = {
focusManager.clearFocus(force = true)
coroutineScope.launch {
withTimeoutOrNull(350) {
withTimeoutOrNull(350.milliseconds) {
snapshotFlow { imeInsets.getBottom(density) > 0 }
.first { visible -> !visible }
}
@@ -201,7 +200,6 @@ fun MainTopBar(
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun SearchField(
searchState: TextFieldState,
enabled: Boolean,
@@ -308,17 +306,15 @@ private fun SearchHistorySheet(
) {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val density = LocalDensity.current
val configuration = LocalConfiguration.current
val screenHeight = LocalConfiguration.current.screenHeightDp.dp
var frozenHeight by remember { mutableStateOf<Dp?>(null) }
if (frozenHeight == null) {
frozenHeight = if (isSearchBarAtBottom) {
configuration.screenHeightDp.dp -
HistorySheetChrome -
with(density) { WindowInsets.navigationBars.getBottom(this).toDp() }
} else {
with(density) {
(configuration.screenHeightDp.dp.toPx() - topBarBottomPx).toDp()
screenHeight - HistorySheetChrome - with(density) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
} else {
screenHeight - with(density) { topBarBottomPx.toDp() }
}
}
val maxContentHeight = frozenHeight!!
@@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfoV2
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.*
@@ -39,7 +38,6 @@ enum class Screen {
Home, Settings, Article, About
}
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun AppNavigation(
searchViewModel: SearchViewModel,
@@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsRoute(
viewModel: SettingsViewModel,
@@ -6,7 +6,6 @@ object Spacing {
// Semantic spacing constants for specific UI elements
val topBarPadding = 8.dp
val topBarHeight = 56.dp
val searchTextStart = 68.dp
val listItemVertical = 8.dp
val contentStart = 32.dp