Add a search bar position setting and render the bar above the results or below them, with window insets applied to match.
172 lines
6.9 KiB
Kotlin
172 lines
6.9 KiB
Kotlin
package com.example.research
|
|
|
|
import android.app.Application
|
|
import com.example.research.common.progress.DictionaryProgressStateHolder
|
|
import com.example.research.common.util.NotificationHelper
|
|
import com.example.research.core.domain.model.AppTheme
|
|
import com.example.research.data.local.preferences.PreferencesManager
|
|
import com.example.research.data.local.preferences.SectionExpansionStates
|
|
import com.example.research.data.repository.LocalDictionaryRepository
|
|
import com.example.research.feature.download.DownloadManager
|
|
import com.example.research.feature.download.repository.DictionaryRepository
|
|
import com.example.research.common.util.FileStorageManager
|
|
import com.example.research.feature.import.DictionaryImportManager
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
import kotlinx.coroutines.flow.asStateFlow
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.coroutines.launch
|
|
import okhttp3.OkHttpClient
|
|
import okhttp3.Protocol
|
|
|
|
/**
|
|
* Values a cold start needs before the first composed frame: the initial
|
|
* theme, locale, empty-library navigation seed, and settings expansion state.
|
|
*/
|
|
data class InitialLaunch(
|
|
val theme: AppTheme,
|
|
val language: String,
|
|
val seedNoDictionaries: Boolean,
|
|
val sectionExpansion: SectionExpansionStates,
|
|
)
|
|
|
|
class ReSearchApplication : Application() {
|
|
|
|
lateinit var preferencesManager: PreferencesManager
|
|
private set
|
|
|
|
lateinit var localDictionaryRepository: LocalDictionaryRepository
|
|
private set
|
|
|
|
lateinit var downloadDictionaryRepository: DictionaryRepository
|
|
private set
|
|
|
|
lateinit var downloadManager: DownloadManager
|
|
private set
|
|
|
|
lateinit var dictionaryImportManager: DictionaryImportManager
|
|
private set
|
|
|
|
lateinit var okHttpClient: OkHttpClient
|
|
private set
|
|
lateinit var dictionaryProgressStateHolder: DictionaryProgressStateHolder
|
|
private set
|
|
lateinit var dictionaryProgressPresenter: com.example.research.common.progress.DictionaryProgressPresenter
|
|
private set
|
|
lateinit var dictionaryPipelineCoordinator: com.example.research.common.progress.DictionaryPipelineCoordinator
|
|
private set
|
|
private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
|
|
private val _initialLaunch = MutableStateFlow<InitialLaunch?>(null)
|
|
val initialLaunch: StateFlow<InitialLaunch?> = _initialLaunch.asStateFlow()
|
|
|
|
override fun onCreate() {
|
|
super.onCreate()
|
|
|
|
val notificationHelper = NotificationHelper(this)
|
|
notificationHelper.cancelProgressNotification()
|
|
|
|
preferencesManager = PreferencesManager(this)
|
|
applicationScope.launch(Dispatchers.IO) {
|
|
preferencesManager.sanitizeDictionarySources()
|
|
}
|
|
applicationScope.launch(Dispatchers.IO) {
|
|
_initialLaunch.value = loadInitialLaunch()
|
|
}
|
|
localDictionaryRepository = LocalDictionaryRepository(this, preferencesManager = preferencesManager)
|
|
|
|
okHttpClient = OkHttpClient.Builder()
|
|
.protocols(listOf(Protocol.HTTP_1_1))
|
|
.build()
|
|
|
|
val fileStorageManager = FileStorageManager()
|
|
|
|
downloadDictionaryRepository = DictionaryRepository(
|
|
context = this,
|
|
preferencesManager = preferencesManager,
|
|
fileStorageManager = fileStorageManager,
|
|
client = okHttpClient
|
|
)
|
|
|
|
downloadManager = DownloadManager(
|
|
dictionaryRepository = downloadDictionaryRepository,
|
|
unknownErrorMessage = getString(R.string.unknown_error),
|
|
sourceUnavailableMessage = getString(R.string.download_file_not_found)
|
|
)
|
|
|
|
dictionaryImportManager = DictionaryImportManager(
|
|
application = this
|
|
)
|
|
|
|
dictionaryProgressStateHolder = DictionaryProgressStateHolder(
|
|
scope = applicationScope,
|
|
downloadManager = downloadManager,
|
|
dictionaryImportManager = dictionaryImportManager,
|
|
localDictionaryRepository = localDictionaryRepository,
|
|
)
|
|
|
|
dictionaryProgressPresenter = com.example.research.common.progress.DictionaryProgressPresenter(
|
|
scope = applicationScope,
|
|
progressSnapshot = dictionaryProgressStateHolder.progressSnapshot,
|
|
notifications = notificationHelper,
|
|
)
|
|
|
|
dictionaryPipelineCoordinator = com.example.research.common.progress.DictionaryPipelineCoordinator(
|
|
scope = applicationScope,
|
|
steps = com.example.research.common.progress.DefaultReindexingSteps(
|
|
localDictionaryRepository = localDictionaryRepository,
|
|
downloadDictionaryRepository = downloadDictionaryRepository,
|
|
),
|
|
importOperations = dictionaryImportManager,
|
|
ui = dictionaryProgressPresenter,
|
|
dictionaryPath = { preferencesManager.dictionaryPath },
|
|
finishService = {
|
|
val intent = android.content.Intent(
|
|
this,
|
|
com.example.research.feature.download.service.DictionaryForegroundService::class.java
|
|
).apply {
|
|
action = com.example.research.feature.download.service.DictionaryForegroundService.ACTION_FINISH
|
|
}
|
|
try {
|
|
startService(intent)
|
|
} catch (_: Exception) {
|
|
}
|
|
},
|
|
)
|
|
|
|
dictionaryImportManager.onFlowStarted = { dictionaryProgressPresenter.beginFlow() }
|
|
dictionaryImportManager.onTerminal = dictionaryPipelineCoordinator::onImportTerminal
|
|
downloadManager.onFlowStarted = { dictionaryProgressPresenter.beginFlow() }
|
|
downloadManager.onDownloadSuccess = dictionaryPipelineCoordinator::onDownloadSuccess
|
|
downloadManager.onTerminal = dictionaryPipelineCoordinator::onDownloadTerminal
|
|
}
|
|
|
|
private suspend fun loadInitialLaunch(): InitialLaunch {
|
|
val defaultExpansions = SectionExpansionStates(
|
|
isThemeExpanded = false,
|
|
isLanguageExpanded = false,
|
|
isSearchBarExpanded = false,
|
|
isDictionariesExpanded = true,
|
|
)
|
|
return InitialLaunch(
|
|
theme = runCatching { AppTheme.valueOf(preferencesManager.themeMode.first()) }
|
|
.getOrDefault(AppTheme.SYSTEM),
|
|
language = runCatching { preferencesManager.language.first() }.getOrDefault("system"),
|
|
seedNoDictionaries = runCatching { preferencesManager.hadNoDictionaries.first() }
|
|
.getOrDefault(true),
|
|
sectionExpansion = runCatching { preferencesManager.sectionExpansionStates() }
|
|
.getOrDefault(defaultExpansions),
|
|
)
|
|
}
|
|
|
|
override fun onTrimMemory(level: Int) {
|
|
super.onTrimMemory(level)
|
|
if (::localDictionaryRepository.isInitialized) {
|
|
localDictionaryRepository.trimMemory(level)
|
|
}
|
|
}
|
|
}
|