summaryrefslogtreecommitdiff
path: root/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2024-01-02 17:53:12 +0100
committerLeonard Kugis <leonard@kug.is>2024-01-02 17:53:12 +0100
commit5db0bdfdf62ae0915b587399a0ff4ce53bca813b (patch)
tree538a18ce0adbf6e600ee77a48e51d8c67649b0c6 /app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
parent298dff2a877680e928b37e3a1336dc7d7aa52dfb (diff)
Implemented route mode
Diffstat (limited to 'app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt')
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt84
1 files changed, 84 insertions, 0 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
index 7b456d1..b70ae36 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
@@ -35,6 +35,10 @@ import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
+import android.app.Activity
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import androidx.documentfile.provider.DocumentFile
import com.google.android.material.textfield.TextInputLayout
import com.google.android.material.textfield.TextInputLayout.END_ICON_CUSTOM
import com.google.android.material.textfield.TextInputLayout.END_ICON_NONE
@@ -60,6 +64,10 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
+import java.io.File
class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) {
@@ -206,6 +214,25 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
}
}
+ private fun validateBounds(inputLayout: TextInputLayout, minValue: Float, maxValue: Float): Boolean {
+ return try {
+ val value = inputLayout.editText?.text?.toString()?.toFloat()!!
+
+ if (value > maxValue || value < minValue) {
+ throw NumberFormatException("value $value is out of bounds")
+ }
+ inputLayout.error = null
+
+ inputLayout.setEndIconDrawable(R.drawable.ic_valid)
+ inputLayout.endIconMode = END_ICON_CUSTOM
+ true
+ } catch (e: Exception) {
+ inputLayout.endIconMode = END_ICON_NONE
+ inputLayout.error = getString(R.string.location_error_bounds)
+ false
+ }
+ }
+
private fun validateCoordinate(
inputLayout: TextInputLayout,
maxValue: Float
@@ -261,16 +288,19 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
@Suppress("UNUSED_PARAMETER")
private fun onAltitudeTextChanged(editable: Editable?) {
+ if(!validateBounds(binding.textlayoutAltitude, -100000.0f, 100000.0f)) return
updateMockLocationParameters()
}
@Suppress("UNUSED_PARAMETER")
private fun onSpeedTextChanged(editable: Editable?) {
+ if(!validateBounds(binding.textlayoutSpeed, 0.0f, 299792458.0f)) return
updateMockLocationParameters()
}
@Suppress("UNUSED_PARAMETER")
private fun onJitterTextChanged(editable: Editable?) {
+ if(!validateBounds(binding.textlayoutJitter, 0.0f, 10000000.0f)) return
updateMockLocationParameters()
}
@@ -305,6 +335,35 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
}
}
+ private var route: List<FakeLocationCoordinate>? = null
+
+ private val filePickerLauncher =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == Activity.RESULT_OK) {
+ result.data?.data?.let { uri ->
+ if(uri.path != null) {
+ var routeFile = File(uri.path ?: ".")
+ //val filePath = selectedFile?.uri?.path ?: "Path not found"
+ //binding.locationRoutePath.text = "Path: $filePath"
+ route = Gson().fromJson(routeFile.readText(Charsets.UTF_8), object : TypeToken<List<FakeLocationCoordinate>>() {}.type)
+ var route_buf = route
+ route_buf?.let {
+ viewModel.submitAction(Action.SetRoute(route_buf))
+ }
+ }
+ }
+ }
+ }
+
+ private fun openFilePicker() {
+ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
+ addCategory(Intent.CATEGORY_OPENABLE)
+ type = "*/*"
+ }
+
+ filePickerLauncher.launch(intent)
+ }
+
@SuppressLint("ClickableViewAccessibility")
private fun bindClickListeners() {
binding.radioUseRealLocation.setOnClickListener {
@@ -320,6 +379,9 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
)
}
}
+ binding.radioUseRoute.setOnClickListener {
+ viewModel.submitAction(Action.UseRoute)
+ }
binding.edittextAltitude.addTextChangedListener(afterTextChanged = ::onAltitudeTextChanged)
binding.edittextSpeed.addTextChangedListener(afterTextChanged = ::onSpeedTextChanged)
@@ -331,6 +393,11 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
binding.edittextJitter.onFocusChangeListener = latLonOnFocusChangeListener
binding.edittextLatitude.onFocusChangeListener = latLonOnFocusChangeListener
binding.edittextLongitude.onFocusChangeListener = latLonOnFocusChangeListener
+
+ binding.buttonLocationRoutePathSelect.setOnClickListener { openFilePicker() }
+ binding.checkboxRouteLoop.setOnCheckedChangeListener { _, isChecked -> viewModel.submitAction(Action.SetRouteLoopEnabledAction(isChecked)) }
+ binding.buttonLocationRouteStart.setOnClickListener { viewModel.submitAction(Action.RouteStartAction) }
+ binding.buttonLocationRouteStop.setOnClickListener { viewModel.submitAction(Action.RouteStopAction) }
}
@SuppressLint("MissingPermission")
@@ -341,12 +408,23 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
binding.radioUseRealLocation.isChecked = state.mode == LocationMode.REAL_LOCATION
+ binding.radioUseRoute.isChecked = state.mode == LocationMode.ROUTE
+
binding.mapView.isEnabled = (state.mode == LocationMode.SPECIFIC_LOCATION)
binding.textlayoutAltitude.isVisible = state.mode == LocationMode.SPECIFIC_LOCATION
binding.textlayoutSpeed.isVisible = state.mode == LocationMode.SPECIFIC_LOCATION
binding.textlayoutJitter.isVisible = state.mode == LocationMode.SPECIFIC_LOCATION
+ binding.buttonLocationRoutePathSelect.isVisible = state.mode == LocationMode.ROUTE
+ binding.locationRoutePath.isVisible = state.mode == LocationMode.ROUTE
+ binding.checkboxRouteLoop.isVisible = state.mode == LocationMode.ROUTE
+ binding.buttonLocationRouteStart.isVisible = state.mode == LocationMode.ROUTE
+ binding.buttonLocationRouteStop.isVisible = state.mode == LocationMode.ROUTE
+
+ if(binding.checkboxRouteLoop.isVisible)
+ binding.checkboxRouteLoop.isChecked = state.loopRoute
+
if(!binding.edittextAltitude.isFocused)
binding.edittextAltitude.setText(state.altitude?.toString())
@@ -379,6 +457,12 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
binding.edittextLatitude.setText(state.specificLatitude?.toString())
binding.edittextLongitude.setText(state.specificLongitude?.toString())
}
+
+ if(route == null) {
+ binding.locationRoutePath.text = "No valid route selected"
+ } else {
+ binding.locationRoutePath.text = "Route valid"
+ }
}
@SuppressLint("MissingPermission")