From 1644690880703083fba5a4e80151b0abc8d28204 Mon Sep 17 00:00:00 2001 From: Filipp Vakhitov Date: Fri, 24 May 2024 22:57:14 +0300 Subject: [PATCH] Support customizing searx instance --- .../app/searchengine/SearchEngineActivity.kt | 24 ++++++++++++++++++- .../app/searchengine/SearchEngineViewModel.kt | 22 +++++++++-------- .../app/settings/db/SettingsDataStore.kt | 4 +++- .../res/layout/activity_search_engine.xml | 7 ++++++ app/src/main/res/values/strings.xml | 10 ++++---- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineActivity.kt b/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineActivity.kt index f2687f521735..ba25ced7d8b8 100644 --- a/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineActivity.kt +++ b/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineActivity.kt @@ -17,6 +17,7 @@ package com.duckduckgo.app.searchengine import android.os.Bundle +import android.view.inputmethod.EditorInfo import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope @@ -30,6 +31,9 @@ import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.appbuildconfig.api.AppBuildConfig import com.duckduckgo.common.ui.DuckDuckGoActivity import com.duckduckgo.common.ui.view.dialog.RadioListAlertDialogBuilder +import com.duckduckgo.common.ui.view.hide +import com.duckduckgo.common.ui.view.hideKeyboard +import com.duckduckgo.common.ui.view.show import com.duckduckgo.common.ui.viewbinding.viewBinding import com.duckduckgo.di.scopes.ActivityScope import kotlinx.coroutines.flow.launchIn @@ -55,12 +59,20 @@ class SearchEngineActivity : DuckDuckGoActivity() { setContentView(binding.root) setupToolbar(binding.includeToolbar.toolbar) - configureUiEventHandlers() + configureUiEventHandlers() observeViewModel() } private fun configureUiEventHandlers() { binding.searchEngineSetting.setClickListener { viewModel.userRequestedToChangeSearchEngine() } + binding.searxInstanceSetting.setOnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + viewModel.onSearxInstanceUpdated(binding.searxInstanceSetting.text) + binding.searxInstanceSetting.hideKeyboard() + return@setOnEditorActionListener true + } + return@setOnEditorActionListener false + } } private fun observeViewModel() { @@ -69,6 +81,7 @@ class SearchEngineActivity : DuckDuckGoActivity() { .onEach { viewState -> viewState.let { updateSelectedSearchEngine(it.selectedSearchEngine) + updateSelectedSearxInstance(it.selectedSearchEngine, it.selectedSearxInstance) } }.launchIn(lifecycleScope) @@ -83,6 +96,15 @@ class SearchEngineActivity : DuckDuckGoActivity() { binding.searchEngineSetting.setSecondaryText(subtitle) } + private fun updateSelectedSearxInstance(searchEngine: SearchEngine, searxInstance: String) { + if (searchEngine is SearxSearchEngine) { + binding.searxInstanceSetting.show() + } else { + binding.searxInstanceSetting.hide() + } + binding.searxInstanceSetting.text = searxInstance + } + private fun processCommand(it: Command) { when (it) { is Command.LaunchSearchEngineSettings -> launchSearchEngineSelector(it.searchEngine) diff --git a/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineViewModel.kt b/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineViewModel.kt index 200a1cf8f109..d852bfa3f9a1 100644 --- a/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/searchengine/SearchEngineViewModel.kt @@ -19,9 +19,8 @@ package com.duckduckgo.app.searchengine import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.duckduckgo.anvil.annotations.ContributesViewModel -import com.duckduckgo.app.settings.clear.ClearWhatOption -import com.duckduckgo.app.settings.clear.ClearWhenOption import com.duckduckgo.app.settings.db.SettingsDataStore +import com.duckduckgo.app.settings.db.SettingsSharedPreferences import com.duckduckgo.di.scopes.ActivityScope import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST import kotlinx.coroutines.channels.Channel @@ -41,12 +40,7 @@ class SearchEngineViewModel @Inject constructor( data class ViewState( val selectedSearchEngine: SearchEngine = DuckDuckGoSearchEngine, - ) - - data class AutomaticallyClearData( - val clearWhatOption: ClearWhatOption, - val clearWhenOption: ClearWhenOption, - val clearWhenOptionEnabled: Boolean = true, + val selectedSearxInstance: String = SettingsSharedPreferences.DEFAULT_SEARX_INSTANCE, ) sealed class Command { @@ -61,6 +55,7 @@ class SearchEngineViewModel @Inject constructor( viewState.emit( ViewState( selectedSearchEngine = settingsDataStore.searchEngine, + selectedSearxInstance = settingsDataStore.searxInstance, ), ) } @@ -85,8 +80,15 @@ class SearchEngineViewModel @Inject constructor( } } - private fun isAutomaticallyClearingDataWhenSettingEnabled(clearWhatOption: ClearWhatOption?): Boolean { - return clearWhatOption != null && clearWhatOption != ClearWhatOption.CLEAR_NONE + fun onSearxInstanceUpdated(searxInstance: String) { + if (settingsDataStore.searxInstance == searxInstance) { + Timber.v("User selected same thing they already have set: $searxInstance; no need to do anything else") + return + } + settingsDataStore.searxInstance = searxInstance + viewModelScope.launch { + viewState.emit(currentViewState().copy(selectedSearxInstance = searxInstance)) + } } private fun currentViewState(): ViewState { diff --git a/app/src/main/java/com/duckduckgo/app/settings/db/SettingsDataStore.kt b/app/src/main/java/com/duckduckgo/app/settings/db/SettingsDataStore.kt index d6ea7b8bc2a4..cf45a3b9ae60 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/db/SettingsDataStore.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/db/SettingsDataStore.kt @@ -195,7 +195,7 @@ class SettingsSharedPreferences @Inject constructor( } override var searxInstance: String - get() = preferences.getString(SEARX_INSTANCE, null) ?: "https://searx.hu/" + get() = preferences.getString(SEARX_INSTANCE, null) ?: DEFAULT_SEARX_INSTANCE set(value) = preferences.edit { putString(SEARX_INSTANCE, value) } override fun hasBackgroundTimestampRecorded(): Boolean = preferences.contains(KEY_APP_BACKGROUNDED_TIMESTAMP) @@ -249,6 +249,8 @@ class SettingsSharedPreferences @Inject constructor( } companion object { + const val DEFAULT_SEARX_INSTANCE = "https://searx.hu/" + const val FILENAME = "com.duckduckgo.app.settings_activity.settings" const val KEY_BACKGROUND_JOB_ID = "BACKGROUND_JOB_ID" const val KEY_AUTOCOMPLETE_ENABLED = "AUTOCOMPLETE_ENABLED" diff --git a/app/src/main/res/layout/activity_search_engine.xml b/app/src/main/res/layout/activity_search_engine.xml index 8c0a0a036650..83346810ba34 100644 --- a/app/src/main/res/layout/activity_search_engine.xml +++ b/app/src/main/res/layout/activity_search_engine.xml @@ -45,6 +45,13 @@ app:primaryTextTruncated="false" tools:secondaryText="test test test" /> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9c2840ae3987..31fd9475879a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -178,6 +178,11 @@ Search engine + Search Engine + DuckDuckGo + Searx + Save + Searx instance Permissions @@ -203,11 +208,6 @@ App exit, inactive for 30 minutes App exit, inactive for 1 hour - Search Engine - DuckDuckGo - Searx - Save - About DuckDuckGo Welcome to the Duck Side!