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:
1 parent
e9706ab12a
commit
92fc5562db
15 files changed
+62
-82
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(
|
||||
context,
|
||||
android.Manifest.permission.POST_NOTIFICATIONS
|
||||
) == android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
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 */ }
|
||||
|
||||
+7
-7
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-21
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -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,13 +81,9 @@ 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)
|
||||
}
|
||||
activeDictionaries.any { dict ->
|
||||
val fileName = dict.path.substringAfterLast("/")
|
||||
!DictionaryConfig.isDabkrsDictionary(fileName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user