Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .clabot
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"ajbruin",
"hoejmann",
"brandsimon",
"sideeffffect"
"sideeffffect",
"T0astBread"
],
"label": "cla-signed ✔️",
"message": "Thank you for your pull request and welcome to our community! We require contributors to sign our [Contributor License Agreement](https://github.com/grote/Transportr/blob/master/CLA.md), and we don't seem to have the user {{usersWithoutCLA}} on file. In order for your code to get reviewed and merged, please explicitly state that you accept the agreement."
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/de/grobox/transportr/TransportrActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import de.grobox.transportr.networks.PickTransportNetworkActivity
import de.grobox.transportr.networks.PickTransportNetworkActivity.Companion.FORCE_NETWORK_SELECTION
import de.grobox.transportr.networks.TransportNetworkManager
import de.grobox.transportr.settings.SettingsManager
import de.grobox.transportr.utils.updateGlobalHttpProxy
import java.util.*
import javax.inject.Inject

Expand All @@ -50,6 +51,7 @@ abstract class TransportrActivity : AppCompatActivity() {
useLanguage()
AppCompatDelegate.setDefaultNightMode(settingsManager.theme)
ensureTransportNetworkSelected()
updateGlobalHttpProxy(settingsManager.proxy, manager)

super.onCreate(savedInstanceState)
}
Expand Down Expand Up @@ -120,5 +122,4 @@ abstract class TransportrActivity : AppCompatActivity() {
finish()
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import android.content.Context
import android.location.Geocoder
import androidx.annotation.WorkerThread
import com.mapbox.mapboxsdk.geometry.LatLng
import de.grobox.transportr.settings.SettingsManager
import de.grobox.transportr.utils.hasLocation
import de.schildbach.pte.dto.Location
import de.schildbach.pte.dto.LocationType.ADDRESS
Expand All @@ -31,12 +32,17 @@ import okhttp3.*
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
import java.net.Proxy
import java.util.*
import javax.inject.Inject
import kotlin.concurrent.thread


class ReverseGeocoder(private val context: Context, private val callback: ReverseGeocoderCallback) {

@Inject
lateinit var settingsManager: SettingsManager

fun findLocation(location: Location) {
if (!location.hasLocation()) return
findLocation(location.latAsDouble, location.lonAsDouble)
Expand Down Expand Up @@ -82,7 +88,9 @@ class ReverseGeocoder(private val context: Context, private val callback: Revers
}

private fun findLocationWithOsm(lat: Double, lon: Double) {
val client = OkHttpClient()
val client = OkHttpClient.Builder()
.proxy(settingsManager.proxy)
.build()

// https://nominatim.openstreetmap.org/reverse?lat=52.5217&lon=13.4324&format=json
val url = StringBuilder("https://nominatim.openstreetmap.org/reverse?")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,22 @@ import androidx.core.app.ActivityOptionsCompat
import androidx.lifecycle.Observer
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.common.net.HostSpecifier
import com.google.common.net.InternetDomainName
import de.grobox.transportr.R
import de.grobox.transportr.TransportrApplication
import de.grobox.transportr.map.MapActivity
import de.grobox.transportr.networks.PickTransportNetworkActivity
import de.grobox.transportr.networks.TransportNetwork
import de.grobox.transportr.networks.TransportNetworkManager
import de.grobox.transportr.settings.SettingsManager.Companion.LANGUAGE
import de.grobox.transportr.settings.SettingsManager.Companion.PROXY_ENABLE
import de.grobox.transportr.settings.SettingsManager.Companion.PROXY_HOST
import de.grobox.transportr.settings.SettingsManager.Companion.PROXY_PORT
import de.grobox.transportr.settings.SettingsManager.Companion.PROXY_PROTOCOL
import de.grobox.transportr.settings.SettingsManager.Companion.THEME
import de.grobox.transportr.ui.ValidatedEditTextPreference
import de.grobox.transportr.utils.updateGlobalHttpProxy
import javax.inject.Inject

class SettingsFragment : PreferenceFragmentCompat() {
Expand All @@ -45,6 +53,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
val TAG: String = SettingsFragment::class.java.simpleName
}

@Inject
internal lateinit var settingsManager: SettingsManager

@Inject
internal lateinit var manager: TransportNetworkManager
private lateinit var networkPref: Preference
Expand Down Expand Up @@ -91,6 +102,34 @@ class SettingsFragment : PreferenceFragmentCompat() {
true
}
}

arrayOf(PROXY_ENABLE, PROXY_HOST, PROXY_PORT, PROXY_PROTOCOL).forEach { prefKey ->
(findPreference(prefKey) as Preference?)?.let { pref ->
pref.setOnPreferenceChangeListener { _, _ ->
updateGlobalHttpProxy(settingsManager.proxy, manager)
true
}
}
}

findPreference<ValidatedEditTextPreference>(PROXY_HOST)!!.validate = { value ->
/*
FIXME: These validation functions are marked unstable, maybe find a replacement

Valid should be everything accepted by InetAddress.getByName(...),
that is: IPv4 addresses, IPv6 addresses, hostnames and FQDNs.

Additionally, no network requests should be performed as part of
the validation, so simply using InetAddress.getByName(...) with a
try/catch is out of the question since it might try to resolve
domain names.
*/
InternetDomainName.isValid(value) || HostSpecifier.isValid(value)
}

findPreference<ValidatedEditTextPreference>(PROXY_PORT)!!.validate = { value ->
value.toIntOrNull() in 1..65534
}
}

private fun onTransportNetworkChanged(network: TransportNetwork) {
Expand Down
31 changes: 31 additions & 0 deletions app/src/main/java/de/grobox/transportr/settings/SettingsManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.preference.PreferenceManager
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate.*
import de.grobox.transportr.R
import de.schildbach.pte.NetworkId
import de.schildbach.pte.NetworkProvider.Optimize
import de.schildbach.pte.NetworkProvider.WalkSpeed
import java.lang.Exception
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.*
import javax.inject.Inject

Expand Down Expand Up @@ -92,6 +97,26 @@ class SettingsManager @Inject constructor(private val context: Context) {
}
}

val proxy: Proxy
get() {
if (!settings.getBoolean(PROXY_ENABLE, false))
return Proxy.NO_PROXY
return try {
val typeStr = settings.getString(PROXY_PROTOCOL, null)
val type = when (typeStr) {
"SOCKS" -> Proxy.Type.SOCKS
"HTTP" -> Proxy.Type.HTTP
else -> throw IllegalStateException("Illegal proxy type: " + typeStr)
}
val host = settings.getString(PROXY_HOST, null)
val port = Integer.parseInt(settings.getString(PROXY_PORT, null)!!)
Proxy(type, InetSocketAddress(InetAddress.getByName(host), port))
} catch (e: Exception) {
Log.e(TAG, "Error parsing proxy settings", e)
Proxy.NO_PROXY
}
}

fun showLocationFragmentOnboarding(): Boolean = settings.getBoolean(LOCATION_ONBOARDING, true)
fun locationFragmentOnboardingShown() {
settings.edit().putBoolean(LOCATION_ONBOARDING, false).apply()
Expand Down Expand Up @@ -136,6 +161,8 @@ class SettingsManager @Inject constructor(private val context: Context) {
}

companion object {
private const val TAG = "SettingsManager"

private const val NETWORK_ID_1 = "NetworkId"
private const val NETWORK_ID_2 = "NetworkId2"
private const val NETWORK_ID_3 = "NetworkId3"
Expand All @@ -147,6 +174,10 @@ class SettingsManager @Inject constructor(private val context: Context) {
private const val OPTIMIZE = "pref_key_optimize"
private const val LOCATION_ONBOARDING = "locationOnboarding"
private const val TRIP_DETAIL_ONBOARDING = "tripDetailOnboarding"
internal const val PROXY_ENABLE = "pref_key_proxy_enable"
internal const val PROXY_PROTOCOL = "pref_key_proxy_protocol"
internal const val PROXY_HOST = "pref_key_proxy_host"
internal const val PROXY_PORT = "pref_key_proxy_port"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Transportr
*
* Copyright (c) 2013 - 2020 Torsten Grote
*
* This program is Free Software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.grobox.transportr.ui

import android.content.Context
import android.content.res.TypedArray
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.preference.Preference
import de.grobox.transportr.R

/**
* An editable text preference that gives immediate user feedback by
* disabling the "OK" button of the edit dialog if the entered text
* does not match the validation criteria.
*
* Validation can be configured by setting the <code>validate</code>
* property.
*/
class ValidatedEditTextPreference(ctx: Context, attrs: AttributeSet) :
Preference(ctx, attrs, R.attr.preferenceStyle) {

var validate: ((String) -> Boolean) = { true }
private var persistedValue: String = ""
private var currentValue: String = persistedValue

init {
setSummaryProvider { persistedValue }

setOnPreferenceClickListener {
currentValue = persistedValue

val dialog = AlertDialog.Builder(ctx)
.setTitle(title)
.setView(R.layout.dialog_validated_edit_text_preference)
.setCancelable(true)
.setPositiveButton(R.string.ok) { dialogInterface, _ ->
dialogInterface.dismiss()
persistString(currentValue)
persistedValue = currentValue
notifyChanged()
}
.setNegativeButton(R.string.cancel) { dialogInterface, _ ->
dialogInterface.cancel()
currentValue = persistedValue
}
.create()
dialog.show()

val editText = dialog.findViewById<EditText>(R.id.text_input)!!
val okButton = dialog.findViewById<Button>(android.R.id.button1)!!

fun updateUIForValidity() {
okButton.isEnabled = validate(currentValue)
}
updateUIForValidity()

editText.setText(currentValue, TextView.BufferType.NORMAL)
editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

override fun afterTextChanged(text: Editable?) {
currentValue = text.toString()
updateUIForValidity()
}
})
editText.postDelayed({
editText.requestFocus()
editText.setSelection(currentValue.length)
val inputMethodManager = ctx.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}, 100)

true
}
}

override fun onGetDefaultValue(a: TypedArray?, index: Int): String? {
return a!!.getString(index)
}

override fun onSetInitialValue(defaultValue: Any?) {
super.onSetInitialValue(defaultValue)
persistedValue = getPersistedString(defaultValue?.toString()) ?: persistedValue
currentValue = persistedValue
}
}
18 changes: 18 additions & 0 deletions app/src/main/java/de/grobox/transportr/utils/TransportrUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.mapbox.mapboxsdk.http.HttpRequestUtil
import de.grobox.transportr.R
import de.grobox.transportr.networks.TransportNetworkManager
import de.schildbach.pte.AbstractNetworkProvider
import de.schildbach.pte.dto.Location
import de.schildbach.pte.dto.LocationType
import de.schildbach.pte.dto.Product
import de.schildbach.pte.dto.Product.*
import okhttp3.OkHttpClient
import java.net.Proxy
import java.text.DecimalFormat
import kotlin.math.roundToInt

Expand Down Expand Up @@ -114,3 +119,16 @@ object TransportrUtils {
}

fun Location.hasLocation() = hasCoord() && (latAs1E6 != 0 || lonAs1E6 != 0)

fun updateGlobalHttpProxy(newProxy: Proxy, manager: TransportNetworkManager) {
// MapBox
HttpRequestUtil.setOkHttpClient(
OkHttpClient.Builder()
.proxy(newProxy)
.build())
// public-transport-enabler
manager.transportNetwork.value?.let {
if (it.networkProvider is AbstractNetworkProvider)
(it.networkProvider as AbstractNetworkProvider).setProxy(newProxy)
}
}
12 changes: 12 additions & 0 deletions app/src/main/res/layout/dialog_validated_edit_text_preference.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="20dp">

<EditText android:id="@+id/text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</LinearLayout>
11 changes: 11 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,15 @@
</string-array>
<string name="pref_walk_speed_value_default" translatable="false">NORMAL</string>

<!-- Proxy Protocol -->
<string-array name="pref_proxy_protocol_options">
<item>@string/pref_proxy_protocol_socks</item>
<item>@string/pref_proxy_protocol_http</item>
</string-array>
<string-array name="pref_proxy_protocol_values">
<item>@string/pref_proxy_protocol_value_default</item>
<item>HTTP</item>
</string-array>
<string name="pref_proxy_protocol_value_default" translatable="false">SOCKS</string>

</resources>
8 changes: 8 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ and always knows where you are to not miss where to get off the bus.
<string name="pref_walk_speed_fast">Fast</string>
<string name="pref_show_when_locked_title">Show trip even when screen is locked</string>
<string name="pref_show_when_locked_summary">Show over lock screen</string>
<string name="pref_proxy">Internet Proxy</string>
<string name="pref_proxy_enable_title">Use proxy</string>
<string name="pref_proxy_enable_summary">Use a proxy for all internet connections</string>
<string name="pref_proxy_protocol">Proxy protocol</string>
<string name="pref_proxy_protocol_socks">SOCKS</string>
<string name="pref_proxy_protocol_http">HTTP</string>
<string name="pref_proxy_host">Proxy server host</string>
<string name="pref_proxy_port">Proxy server port</string>

<string name="error">Error</string>
<string name="error_no_internet">Internet connection required. Please make sure your internet access is working.</string>
Expand Down
Loading