NetworkPreference: Move out and simply proxy logic
No need to check connectivity as soon as URL is set as SplashFragment will only let you login when a valid connection is available. Use a modern dialog and EditText to do set the URL with minimal verification. Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -43,8 +43,6 @@ object Constants {
|
||||
const val GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
|
||||
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
||||
|
||||
const val ANDROID_CONNECTIVITY_URL = "https://connectivitycheck.android.com/generate_204"
|
||||
|
||||
//ACCOUNTS
|
||||
const val ACCOUNT_SIGNED_IN = "ACCOUNT_SIGNED_IN"
|
||||
const val ACCOUNT_SIGNED_TIMESTAMP = "ACCOUNT_SIGNED_TIMESTAMP"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.aurora.store.data.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class ProxyInfo(
|
||||
var protocol: String,
|
||||
var host: String,
|
||||
var port: Int,
|
||||
var proxyUser: String?,
|
||||
var proxyPassword: String?
|
||||
)
|
||||
) : Parcelable
|
||||
|
||||
@@ -25,7 +25,7 @@ class InputDispenserDialog: DialogFragment() {
|
||||
get() = Preferences.getStringSet(requireContext(), PREFERENCE_DISPENSER_URLS)
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_dispenser_input, null)
|
||||
val view = layoutInflater.inflate(R.layout.dialog_text_input_edit_text, null)
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.add_dispenser_title)
|
||||
.setMessage(R.string.add_dispenser_summary)
|
||||
@@ -37,7 +37,10 @@ class InputDispenserDialog: DialogFragment() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
textInputLayout?.editText?.showKeyboard()
|
||||
textInputLayout?.editText?.apply {
|
||||
hint = requireContext().getString(R.string.add_dispenser_hint)
|
||||
showKeyboard()
|
||||
}
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,33 +19,36 @@
|
||||
|
||||
package com.aurora.store.view.ui.preferences
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.aurora.extensions.runOnUiThread
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.util.CommonUtil
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_ENABLED
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_INFO
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_URL
|
||||
import com.aurora.store.util.remove
|
||||
import com.aurora.store.util.save
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class NetworkPreference : BasePreferenceFragment() {
|
||||
class NetworkPreference : BasePreferenceFragment(),
|
||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private val viewModel: SettingsViewModel by viewModels()
|
||||
private lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_network, rootKey)
|
||||
|
||||
sharedPreferences = Preferences.getPrefs(requireContext())
|
||||
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
|
||||
findPreference<Preference>(Preferences.PREFERENCE_DISPENSER_URLS)?.apply {
|
||||
setOnPreferenceClickListener {
|
||||
findNavController().navigate(R.id.dispenserFragment)
|
||||
@@ -53,18 +56,14 @@ class NetworkPreference : BasePreferenceFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
findPreference<EditTextPreference>(Preferences.PREFERENCE_PROXY_URL)?.let {
|
||||
it.summary =
|
||||
Preferences.getString(requireContext(), Preferences.PREFERENCE_PROXY_URL, "")
|
||||
|
||||
it.setOnPreferenceChangeListener { _, newValue ->
|
||||
val newProxyUrl = newValue.toString()
|
||||
val newProxyInfo = CommonUtil.parseProxyUrl(newProxyUrl)
|
||||
|
||||
if (newProxyInfo == null) {
|
||||
requireContext().toast(getString(R.string.toast_proxy_invalid))
|
||||
findPreference<SwitchPreferenceCompat>(PREFERENCE_PROXY_ENABLED)?.apply {
|
||||
isChecked = Preferences.getString(context, PREFERENCE_PROXY_URL).isNotBlank()
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue.toString().toBoolean()) {
|
||||
findNavController().navigate(R.id.proxyURLDialog)
|
||||
} else {
|
||||
viewModel.saveProxyDetails(newProxyUrl, newProxyInfo)
|
||||
remove(PREFERENCE_PROXY_URL)
|
||||
remove(PREFERENCE_PROXY_INFO)
|
||||
}
|
||||
false
|
||||
}
|
||||
@@ -96,23 +95,17 @@ class NetworkPreference : BasePreferenceFragment() {
|
||||
title = getString(R.string.pref_network_title)
|
||||
setNavigationOnClickListener { findNavController().navigateUp() }
|
||||
}
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.proxyURL.filter { it.isNotBlank() }.collect { pURL ->
|
||||
findPreference<EditTextPreference>(Preferences.PREFERENCE_PROXY_URL)?.let {
|
||||
it.summary = pURL
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onDestroyView() {
|
||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.proxyInfo.collect {
|
||||
if (it == null) {
|
||||
requireContext().toast(getText(R.string.toast_proxy_failed))
|
||||
} else {
|
||||
requireContext().toast(getString(R.string.toast_proxy_success))
|
||||
}
|
||||
}
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == PREFERENCE_PROXY_URL) {
|
||||
findPreference<SwitchPreferenceCompat>(PREFERENCE_PROXY_ENABLED)?.isChecked =
|
||||
Preferences.getString(requireContext(), PREFERENCE_PROXY_URL).isNotBlank()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.aurora.store.view.ui.preferences
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.aurora.extensions.showKeyboard
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.util.CommonUtil
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_INFO
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_URL
|
||||
import com.aurora.store.util.save
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ProxyURLDialog: DialogFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var gson: Gson
|
||||
|
||||
private val textInputLayout: TextInputLayout?
|
||||
get() = dialog?.findViewById(R.id.textInputLayout)
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_text_input_edit_text, null)
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.pref_network_proxy_url)
|
||||
.setMessage(R.string.pref_network_proxy_url_message)
|
||||
.setView(view)
|
||||
.setPositiveButton(getString(R.string.add)) { _, _ -> saveProxyUrl() }
|
||||
.setNegativeButton(getString(android.R.string.cancel)) { _, _ -> dialog?.dismiss()}
|
||||
.create()
|
||||
}
|
||||
|
||||
@SuppressLint("AuthLeak") // False-positive
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
textInputLayout?.editText?.apply {
|
||||
hint = "protocol://user:password@host:port"
|
||||
setText(Preferences.getString(context, PREFERENCE_PROXY_URL))
|
||||
showKeyboard()
|
||||
}
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
}
|
||||
|
||||
private fun saveProxyUrl() {
|
||||
val url = textInputLayout?.editText?.text?.toString()
|
||||
if (url.isNullOrEmpty()) {
|
||||
toast(R.string.add_dispenser_error)
|
||||
return
|
||||
}
|
||||
|
||||
val proxyInfo = CommonUtil.parseProxyUrl(url)
|
||||
if (proxyInfo != null) {
|
||||
save(PREFERENCE_PROXY_URL, url)
|
||||
save(PREFERENCE_PROXY_INFO, gson.toJson(proxyInfo))
|
||||
toast(R.string.toast_proxy_success)
|
||||
return
|
||||
} else {
|
||||
toast(R.string.toast_proxy_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.aurora.store.view.ui.preferences
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.aurora.Constants
|
||||
import com.aurora.store.data.model.ProxyInfo
|
||||
import com.aurora.store.data.network.HttpClient
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_INFO
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_PROXY_URL
|
||||
import com.aurora.store.util.save
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@SuppressLint("StaticFieldLeak") // false positive, see https://github.com/google/dagger/issues/3253
|
||||
class SettingsViewModel @Inject constructor(
|
||||
private val gson: Gson,
|
||||
@ApplicationContext private val context: Context
|
||||
): ViewModel() {
|
||||
|
||||
private val TAG = SettingsViewModel::class.java.simpleName
|
||||
|
||||
private val _proxyURL = MutableStateFlow(String())
|
||||
val proxyURL = _proxyURL.asStateFlow()
|
||||
|
||||
private val _proxyInfo = MutableSharedFlow<ProxyInfo?>()
|
||||
val proxyInfo = _proxyInfo.asSharedFlow()
|
||||
|
||||
fun saveProxyDetails(url: String, info: ProxyInfo) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val result = HttpClient
|
||||
.getPreferredClient(context)
|
||||
.setProxy(info)
|
||||
.get(Constants.ANDROID_CONNECTIVITY_URL, mapOf())
|
||||
|
||||
if (result.code == 204) {
|
||||
context.save(PREFERENCE_PROXY_URL, url)
|
||||
_proxyURL.value = url
|
||||
|
||||
context.save(PREFERENCE_PROXY_INFO, gson.toJson(info))
|
||||
_proxyInfo.emit(info)
|
||||
} else {
|
||||
throw Exception("Failed to set proxy")
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to set proxy", exception)
|
||||
_proxyInfo.emit(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
android:id="@+id/textInputEditText"
|
||||
style="@style/Widget.Material3.TextInputEditText.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/add_dispenser_hint" />
|
||||
android:layout_height="wrap_content" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@@ -484,4 +484,8 @@
|
||||
app:popUpTo="@id/mobile_navigation"
|
||||
app:popUpToInclusive="true" />
|
||||
</dialog>
|
||||
<dialog
|
||||
android:id="@+id/proxyURLDialog"
|
||||
android:name="com.aurora.store.view.ui.preferences.ProxyURLDialog"
|
||||
android:label="@string/pref_network_proxy_url" />
|
||||
</navigation>
|
||||
|
||||
@@ -233,6 +233,7 @@
|
||||
<string name="pref_network_proxy_enable">"Enable proxy"</string>
|
||||
<string name="pref_network_proxy_enable_desc">"Allow all traffic from app to go through the proxy"</string>
|
||||
<string name="pref_network_proxy_url">"Proxy URL"</string>
|
||||
<string name="pref_network_proxy_url_message">Enter a valid proxy URL to pass all data through the proxy.</string>
|
||||
<string name="pref_ui_accent_title">"Accent"</string>
|
||||
<string name="pref_ui_theme_black">"Black"</string>
|
||||
<string name="pref_ui_theme_dark">"Dark"</string>
|
||||
|
||||
@@ -38,12 +38,6 @@
|
||||
app:summary="@string/pref_network_proxy_enable_desc"
|
||||
app:title="@string/pref_network_proxy_enable" />
|
||||
|
||||
<EditTextPreference
|
||||
app:dependency="PREFERENCE_PROXY_ENABLED"
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="PREFERENCE_PROXY_URL"
|
||||
app:title="@string/pref_network_proxy_url" />
|
||||
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:singleLineTitle="false"
|
||||
|
||||
Reference in New Issue
Block a user