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 GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
|
||||||
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
||||||
|
|
||||||
const val ANDROID_CONNECTIVITY_URL = "https://connectivitycheck.android.com/generate_204"
|
|
||||||
|
|
||||||
//ACCOUNTS
|
//ACCOUNTS
|
||||||
const val ACCOUNT_SIGNED_IN = "ACCOUNT_SIGNED_IN"
|
const val ACCOUNT_SIGNED_IN = "ACCOUNT_SIGNED_IN"
|
||||||
const val ACCOUNT_SIGNED_TIMESTAMP = "ACCOUNT_SIGNED_TIMESTAMP"
|
const val ACCOUNT_SIGNED_TIMESTAMP = "ACCOUNT_SIGNED_TIMESTAMP"
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.aurora.store.data.model
|
package com.aurora.store.data.model
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
data class ProxyInfo(
|
data class ProxyInfo(
|
||||||
var protocol: String,
|
var protocol: String,
|
||||||
var host: String,
|
var host: String,
|
||||||
var port: Int,
|
var port: Int,
|
||||||
var proxyUser: String?,
|
var proxyUser: String?,
|
||||||
var proxyPassword: String?
|
var proxyPassword: String?
|
||||||
)
|
) : Parcelable
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class InputDispenserDialog: DialogFragment() {
|
|||||||
get() = Preferences.getStringSet(requireContext(), PREFERENCE_DISPENSER_URLS)
|
get() = Preferences.getStringSet(requireContext(), PREFERENCE_DISPENSER_URLS)
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
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())
|
return MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle(R.string.add_dispenser_title)
|
.setTitle(R.string.add_dispenser_title)
|
||||||
.setMessage(R.string.add_dispenser_summary)
|
.setMessage(R.string.add_dispenser_summary)
|
||||||
@@ -37,7 +37,10 @@ class InputDispenserDialog: DialogFragment() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.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)
|
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,33 +19,36 @@
|
|||||||
|
|
||||||
package com.aurora.store.view.ui.preferences
|
package com.aurora.store.view.ui.preferences
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.fragment.app.viewModels
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.EditTextPreference
|
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.SwitchPreferenceCompat
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import com.aurora.extensions.runOnUiThread
|
import com.aurora.extensions.runOnUiThread
|
||||||
import com.aurora.extensions.toast
|
import com.aurora.extensions.toast
|
||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.util.CommonUtil
|
|
||||||
import com.aurora.store.util.Preferences
|
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 com.aurora.store.util.save
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.filter
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@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?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.preferences_network, rootKey)
|
setPreferencesFromResource(R.xml.preferences_network, rootKey)
|
||||||
|
|
||||||
|
sharedPreferences = Preferences.getPrefs(requireContext())
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||||
|
|
||||||
findPreference<Preference>(Preferences.PREFERENCE_DISPENSER_URLS)?.apply {
|
findPreference<Preference>(Preferences.PREFERENCE_DISPENSER_URLS)?.apply {
|
||||||
setOnPreferenceClickListener {
|
setOnPreferenceClickListener {
|
||||||
findNavController().navigate(R.id.dispenserFragment)
|
findNavController().navigate(R.id.dispenserFragment)
|
||||||
@@ -53,18 +56,14 @@ class NetworkPreference : BasePreferenceFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findPreference<EditTextPreference>(Preferences.PREFERENCE_PROXY_URL)?.let {
|
findPreference<SwitchPreferenceCompat>(PREFERENCE_PROXY_ENABLED)?.apply {
|
||||||
it.summary =
|
isChecked = Preferences.getString(context, PREFERENCE_PROXY_URL).isNotBlank()
|
||||||
Preferences.getString(requireContext(), Preferences.PREFERENCE_PROXY_URL, "")
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
if (newValue.toString().toBoolean()) {
|
||||||
it.setOnPreferenceChangeListener { _, newValue ->
|
findNavController().navigate(R.id.proxyURLDialog)
|
||||||
val newProxyUrl = newValue.toString()
|
|
||||||
val newProxyInfo = CommonUtil.parseProxyUrl(newProxyUrl)
|
|
||||||
|
|
||||||
if (newProxyInfo == null) {
|
|
||||||
requireContext().toast(getString(R.string.toast_proxy_invalid))
|
|
||||||
} else {
|
} else {
|
||||||
viewModel.saveProxyDetails(newProxyUrl, newProxyInfo)
|
remove(PREFERENCE_PROXY_URL)
|
||||||
|
remove(PREFERENCE_PROXY_INFO)
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -96,23 +95,17 @@ class NetworkPreference : BasePreferenceFragment() {
|
|||||||
title = getString(R.string.pref_network_title)
|
title = getString(R.string.pref_network_title)
|
||||||
setNavigationOnClickListener { findNavController().navigateUp() }
|
setNavigationOnClickListener { findNavController().navigateUp() }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
override fun onDestroyView() {
|
||||||
viewModel.proxyURL.filter { it.isNotBlank() }.collect { pURL ->
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||||
findPreference<EditTextPreference>(Preferences.PREFERENCE_PROXY_URL)?.let {
|
super.onDestroyView()
|
||||||
it.summary = pURL
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
viewModel.proxyInfo.collect {
|
if (key == PREFERENCE_PROXY_URL) {
|
||||||
if (it == null) {
|
findPreference<SwitchPreferenceCompat>(PREFERENCE_PROXY_ENABLED)?.isChecked =
|
||||||
requireContext().toast(getText(R.string.toast_proxy_failed))
|
Preferences.getString(requireContext(), PREFERENCE_PROXY_URL).isNotBlank()
|
||||||
} else {
|
|
||||||
requireContext().toast(getString(R.string.toast_proxy_success))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
android:id="@+id/textInputEditText"
|
||||||
style="@style/Widget.Material3.TextInputEditText.OutlinedBox"
|
style="@style/Widget.Material3.TextInputEditText.OutlinedBox"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
android:hint="@string/add_dispenser_hint" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
@@ -484,4 +484,8 @@
|
|||||||
app:popUpTo="@id/mobile_navigation"
|
app:popUpTo="@id/mobile_navigation"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
</dialog>
|
</dialog>
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/proxyURLDialog"
|
||||||
|
android:name="com.aurora.store.view.ui.preferences.ProxyURLDialog"
|
||||||
|
android:label="@string/pref_network_proxy_url" />
|
||||||
</navigation>
|
</navigation>
|
||||||
|
|||||||
@@ -233,6 +233,7 @@
|
|||||||
<string name="pref_network_proxy_enable">"Enable proxy"</string>
|
<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_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">"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_accent_title">"Accent"</string>
|
||||||
<string name="pref_ui_theme_black">"Black"</string>
|
<string name="pref_ui_theme_black">"Black"</string>
|
||||||
<string name="pref_ui_theme_dark">"Dark"</string>
|
<string name="pref_ui_theme_dark">"Dark"</string>
|
||||||
|
|||||||
@@ -38,12 +38,6 @@
|
|||||||
app:summary="@string/pref_network_proxy_enable_desc"
|
app:summary="@string/pref_network_proxy_enable_desc"
|
||||||
app:title="@string/pref_network_proxy_enable" />
|
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
|
<PreferenceCategory
|
||||||
app:iconSpaceReserved="false"
|
app:iconSpaceReserved="false"
|
||||||
app:singleLineTitle="false"
|
app:singleLineTitle="false"
|
||||||
|
|||||||
Reference in New Issue
Block a user