Loading app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 E FOUNDATION * * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.privacycentralapp.dummy import kotlin.random.Random data class City(val name: String, val latitude: Double, val longitude: Double) { fun toRandomLocation(): Location { return Location(LocationMode.RANDOM_LOCATION, this.latitude, this.longitude) } } object CityDataSource { private val BARCELONA = Pair(41.3851, 2.1734) private val BUDAPEST = Pair(47.4979, 19.0402) private val ABU_DHABI = Pair(24.4539, 54.3773) private val HYDERABAD = Pair(17.3850, 78.4867) private val QUEZON_CITY = Pair(14.6760, 121.0437) private val PARIS = Pair(48.8566, 2.3522) private val LONDON = Pair(51.5074, 0.1278) private val SHANGHAI = Pair(31.2304, 121.4737) private val MADRID = Pair(40.4168, 3.7038) private val LAHORE = Pair(31.5204, 74.3587) private val CHICAGO = Pair(41.8781, 87.6298) // LatLong Array, the order should be the same as that of R.array.cities private val latLongArray = arrayOf( BARCELONA, BUDAPEST, ABU_DHABI, HYDERABAD, QUEZON_CITY, PARIS, LONDON, SHANGHAI, MADRID, LAHORE, CHICAGO ) fun getRandomCity(cities: Array<String>): City { if (cities.size != latLongArray.size) { throw IllegalStateException("LatLong array must have the same number of element as in cities array.") } val randomIndex = Random.nextInt(cities.size) val latLong = latLongArray[randomIndex] return City(cities[randomIndex], latLong.first, latLong.second) } } app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt +4 −1 Original line number Diff line number Diff line Loading @@ -185,7 +185,10 @@ object DummyDataSource { LocationMode.REAL_LOCATION -> _location.value = Location(LocationMode.REAL_LOCATION, 24.39, 71.80) LocationMode.RANDOM_LOCATION -> _location.value = randomLocation() LocationMode.RANDOM_LOCATION -> { requireNotNull(location) { "Custom location should be null" } _location.value = location } LocationMode.CUSTOM_LOCATION -> { requireNotNull(location) { "Custom location should be null" } _location.value = location.copy(mode = LocationMode.CUSTOM_LOCATION) Loading app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt +70 −23 Original line number Diff line number Diff line Loading @@ -18,16 +18,17 @@ package foundation.e.privacycentralapp.features.location import android.util.Log import com.mapbox.mapboxsdk.geometry.LatLng import foundation.e.flowmvi.Actor import foundation.e.flowmvi.Reducer import foundation.e.flowmvi.SingleEventProducer import foundation.e.flowmvi.feature.BaseFeature import foundation.e.privacycentralapp.dummy.CityDataSource import foundation.e.privacycentralapp.dummy.DummyDataSource import foundation.e.privacycentralapp.dummy.Location import foundation.e.privacycentralapp.dummy.LocationMode import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map // Define a state machine for Fake location feature class FakeLocationFeature( Loading @@ -44,10 +45,7 @@ class FakeLocationFeature( { message -> Log.d("FakeLocationFeature", message) }, singleEventProducer ) { sealed class State { object InitialState : State() data class LocationState(val location: Location) : State() } data class State(val location: Location) sealed class SingleEvent { object RandomLocationSelectedEvent : SingleEvent() Loading @@ -57,47 +55,91 @@ class FakeLocationFeature( } sealed class Action { object ObserveLocationAction : Action() data class UpdateLocationAction(val latLng: LatLng) : Action() object UseRealLocationAction : Action() object UseRandomLocationAction : Action() data class UseRandomLocationAction(val cities: Array<String>) : Action() { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as UseRandomLocationAction if (!cities.contentEquals(other.cities)) return false return true } override fun hashCode(): Int { return cities.contentHashCode() } } object UseSpecificLocationAction : Action() data class AddSpecificLocationAction(val latitude: Double, val longitude: Double) : Action() data class SetFakeLocationAction(val latitude: Double, val longitude: Double) : Action() } sealed class Effect { data class LocationUpdatedEffect(val location: Location) : Effect() data class LocationUpdatedEffect(val latitude: Double, val longitude: Double) : Effect() object RealLocationSelectedEffect : Effect() object RandomLocationSelectedEffect : Effect() data class SpecificLocationSelectedEffect(val location: Location) : Effect() object SpecificLocationSelectedEffect : Effect() object SpecificLocationSavedEffect : Effect() data class ErrorEffect(val message: String) : Effect() } companion object { fun create( initialState: State = State.InitialState, initialState: State = State( Location( LocationMode.REAL_LOCATION, 0.0, 0.0 ) ), coroutineScope: CoroutineScope ) = FakeLocationFeature( initialState, coroutineScope, reducer = { state, effect -> when (effect) { Effect.RandomLocationSelectedEffect, Effect.RealLocationSelectedEffect, is Effect.ErrorEffect, Effect.SpecificLocationSavedEffect -> state is Effect.LocationUpdatedEffect -> State.LocationState(effect.location) is Effect.SpecificLocationSelectedEffect -> State.LocationState(effect.location) Effect.RandomLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.RANDOM_LOCATION ) ) Effect.RealLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.REAL_LOCATION ) ) is Effect.ErrorEffect, Effect.SpecificLocationSavedEffect -> state is Effect.LocationUpdatedEffect -> state.copy( location = state.location.copy( latitude = effect.latitude, longitude = effect.longitude ) ) is Effect.SpecificLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.CUSTOM_LOCATION ) ) } }, actor = { _, action -> when (action) { is Action.ObserveLocationAction -> DummyDataSource.location.map { Effect.LocationUpdatedEffect(it) } is Action.AddSpecificLocationAction -> { is Action.UpdateLocationAction -> flowOf( Effect.LocationUpdatedEffect( action.latLng.latitude, action.latLng.longitude ) ) is Action.SetFakeLocationAction -> { val location = Location( LocationMode.CUSTOM_LOCATION, action.latitude, action.longitude ) // TODO: Call fake location api with specific coordinates here. val success = DummyDataSource.setLocationMode( LocationMode.CUSTOM_LOCATION, location Loading @@ -112,8 +154,13 @@ class FakeLocationFeature( ) } } Action.UseRandomLocationAction -> { val success = DummyDataSource.setLocationMode(LocationMode.RANDOM_LOCATION) is Action.UseRandomLocationAction -> { val randomCity = CityDataSource.getRandomCity(action.cities) // TODO: Call fake location api with random location here. val success = DummyDataSource.setLocationMode( LocationMode.RANDOM_LOCATION, randomCity.toRandomLocation() ) if (success) { flowOf( Effect.RandomLocationSelectedEffect Loading @@ -125,6 +172,7 @@ class FakeLocationFeature( } } Action.UseRealLocationAction -> { // TODO: Call turn off fake location api here. val success = DummyDataSource.setLocationMode(LocationMode.REAL_LOCATION) if (success) { flowOf( Loading @@ -137,8 +185,7 @@ class FakeLocationFeature( } } Action.UseSpecificLocationAction -> { val location = DummyDataSource.location.value flowOf(Effect.SpecificLocationSelectedEffect(location.copy(mode = LocationMode.CUSTOM_LOCATION))) flowOf(Effect.SpecificLocationSelectedEffect) } } }, Loading app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt +163 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes app/src/main/res/layout/fragment_fake_location.xml +33 −42 Original line number Diff line number Diff line Loading @@ -3,30 +3,30 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:mapbox="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:layout_height="match_parent" android:layout_width="match_parent" > <Toolbar android:background="@color/white" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:layout_gravity="top|center" android:background="@color/white" android:layout_height="?android:attr/actionBarSize" android:layout_width="match_parent" tools:layout_height="56dp" /> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" android:layout_marginBottom="32dp" android:layout_marginTop="?android:attr/actionBarSize" android:layout_width="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" android:paddingLeft="32dp" android:paddingRight="32dp" Loading @@ -35,9 +35,9 @@ <TextView android:id="@+id/fake_location_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_height="wrap_content" android:layout_width="match_parent" android:paddingTop="16dp" android:text="@string/fake_location_info" android:textColor="@color/black" Loading @@ -45,23 +45,23 @@ /> <TextView android:id="@+id/learn_more_fake_location" android:layout_width="wrap_content" android:layout_height="48dp" android:fontFamily="sans-serif-medium" android:gravity="center_vertical" android:id="@+id/learn_more_fake_location" android:layout_height="48dp" android:layout_width="wrap_content" android:text="@string/learn_more" android:textColor="#007fff" android:textSize="14sp" /> <TextView android:fontFamily="sans-serif-medium" android:id="@+id/my_location_header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="sans-serif-medium" android:paddingTop="16dp" android:layout_width="wrap_content" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="@string/my_location_title" android:textColor="@color/black" android:textSize="14sp" Loading @@ -69,31 +69,31 @@ <RadioGroup android:id="@+id/location_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical" > <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_real_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_real_location" android:textSize="16sp" /> <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_random_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_random_location" android:textSize="16sp" /> <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_specific_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_specific_location" android:textSize="16sp" /> Loading @@ -102,53 +102,44 @@ <foundation.e.privacycentralapp.features.location.FakeLocationMapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="240dp" mapbox:mapbox_cameraZoom="15" android:layout_marginTop="32dp" android:layout_marginBottom="32dp" android:layout_marginTop="32dp" android:layout_width="match_parent" mapbox:mapbox_cameraZoom="8" /> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edittext_longitude" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/longitude" android:id="@+id/edittext_longitude" android:layout_height="wrap_content" android:layout_width="match_parent" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:layout_height="wrap_content" android:layout_width="match_parent" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edittext_latitude" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:hint="@string/latitude" android:id="@+id/edittext_latitude" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:hint="@string/latitude" android:layout_width="match_parent" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:layout_height="wrap_content" android:layout_width="match_parent" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/button_add_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="32dp" android:text="@string/add_location" app:backgroundTint="#007fff" /> </LinearLayout> </androidx.core.widget.NestedScrollView> </FrameLayout> No newline at end of file Loading
app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 E FOUNDATION * * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.privacycentralapp.dummy import kotlin.random.Random data class City(val name: String, val latitude: Double, val longitude: Double) { fun toRandomLocation(): Location { return Location(LocationMode.RANDOM_LOCATION, this.latitude, this.longitude) } } object CityDataSource { private val BARCELONA = Pair(41.3851, 2.1734) private val BUDAPEST = Pair(47.4979, 19.0402) private val ABU_DHABI = Pair(24.4539, 54.3773) private val HYDERABAD = Pair(17.3850, 78.4867) private val QUEZON_CITY = Pair(14.6760, 121.0437) private val PARIS = Pair(48.8566, 2.3522) private val LONDON = Pair(51.5074, 0.1278) private val SHANGHAI = Pair(31.2304, 121.4737) private val MADRID = Pair(40.4168, 3.7038) private val LAHORE = Pair(31.5204, 74.3587) private val CHICAGO = Pair(41.8781, 87.6298) // LatLong Array, the order should be the same as that of R.array.cities private val latLongArray = arrayOf( BARCELONA, BUDAPEST, ABU_DHABI, HYDERABAD, QUEZON_CITY, PARIS, LONDON, SHANGHAI, MADRID, LAHORE, CHICAGO ) fun getRandomCity(cities: Array<String>): City { if (cities.size != latLongArray.size) { throw IllegalStateException("LatLong array must have the same number of element as in cities array.") } val randomIndex = Random.nextInt(cities.size) val latLong = latLongArray[randomIndex] return City(cities[randomIndex], latLong.first, latLong.second) } }
app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt +4 −1 Original line number Diff line number Diff line Loading @@ -185,7 +185,10 @@ object DummyDataSource { LocationMode.REAL_LOCATION -> _location.value = Location(LocationMode.REAL_LOCATION, 24.39, 71.80) LocationMode.RANDOM_LOCATION -> _location.value = randomLocation() LocationMode.RANDOM_LOCATION -> { requireNotNull(location) { "Custom location should be null" } _location.value = location } LocationMode.CUSTOM_LOCATION -> { requireNotNull(location) { "Custom location should be null" } _location.value = location.copy(mode = LocationMode.CUSTOM_LOCATION) Loading
app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt +70 −23 Original line number Diff line number Diff line Loading @@ -18,16 +18,17 @@ package foundation.e.privacycentralapp.features.location import android.util.Log import com.mapbox.mapboxsdk.geometry.LatLng import foundation.e.flowmvi.Actor import foundation.e.flowmvi.Reducer import foundation.e.flowmvi.SingleEventProducer import foundation.e.flowmvi.feature.BaseFeature import foundation.e.privacycentralapp.dummy.CityDataSource import foundation.e.privacycentralapp.dummy.DummyDataSource import foundation.e.privacycentralapp.dummy.Location import foundation.e.privacycentralapp.dummy.LocationMode import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map // Define a state machine for Fake location feature class FakeLocationFeature( Loading @@ -44,10 +45,7 @@ class FakeLocationFeature( { message -> Log.d("FakeLocationFeature", message) }, singleEventProducer ) { sealed class State { object InitialState : State() data class LocationState(val location: Location) : State() } data class State(val location: Location) sealed class SingleEvent { object RandomLocationSelectedEvent : SingleEvent() Loading @@ -57,47 +55,91 @@ class FakeLocationFeature( } sealed class Action { object ObserveLocationAction : Action() data class UpdateLocationAction(val latLng: LatLng) : Action() object UseRealLocationAction : Action() object UseRandomLocationAction : Action() data class UseRandomLocationAction(val cities: Array<String>) : Action() { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as UseRandomLocationAction if (!cities.contentEquals(other.cities)) return false return true } override fun hashCode(): Int { return cities.contentHashCode() } } object UseSpecificLocationAction : Action() data class AddSpecificLocationAction(val latitude: Double, val longitude: Double) : Action() data class SetFakeLocationAction(val latitude: Double, val longitude: Double) : Action() } sealed class Effect { data class LocationUpdatedEffect(val location: Location) : Effect() data class LocationUpdatedEffect(val latitude: Double, val longitude: Double) : Effect() object RealLocationSelectedEffect : Effect() object RandomLocationSelectedEffect : Effect() data class SpecificLocationSelectedEffect(val location: Location) : Effect() object SpecificLocationSelectedEffect : Effect() object SpecificLocationSavedEffect : Effect() data class ErrorEffect(val message: String) : Effect() } companion object { fun create( initialState: State = State.InitialState, initialState: State = State( Location( LocationMode.REAL_LOCATION, 0.0, 0.0 ) ), coroutineScope: CoroutineScope ) = FakeLocationFeature( initialState, coroutineScope, reducer = { state, effect -> when (effect) { Effect.RandomLocationSelectedEffect, Effect.RealLocationSelectedEffect, is Effect.ErrorEffect, Effect.SpecificLocationSavedEffect -> state is Effect.LocationUpdatedEffect -> State.LocationState(effect.location) is Effect.SpecificLocationSelectedEffect -> State.LocationState(effect.location) Effect.RandomLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.RANDOM_LOCATION ) ) Effect.RealLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.REAL_LOCATION ) ) is Effect.ErrorEffect, Effect.SpecificLocationSavedEffect -> state is Effect.LocationUpdatedEffect -> state.copy( location = state.location.copy( latitude = effect.latitude, longitude = effect.longitude ) ) is Effect.SpecificLocationSelectedEffect -> state.copy( location = state.location.copy( mode = LocationMode.CUSTOM_LOCATION ) ) } }, actor = { _, action -> when (action) { is Action.ObserveLocationAction -> DummyDataSource.location.map { Effect.LocationUpdatedEffect(it) } is Action.AddSpecificLocationAction -> { is Action.UpdateLocationAction -> flowOf( Effect.LocationUpdatedEffect( action.latLng.latitude, action.latLng.longitude ) ) is Action.SetFakeLocationAction -> { val location = Location( LocationMode.CUSTOM_LOCATION, action.latitude, action.longitude ) // TODO: Call fake location api with specific coordinates here. val success = DummyDataSource.setLocationMode( LocationMode.CUSTOM_LOCATION, location Loading @@ -112,8 +154,13 @@ class FakeLocationFeature( ) } } Action.UseRandomLocationAction -> { val success = DummyDataSource.setLocationMode(LocationMode.RANDOM_LOCATION) is Action.UseRandomLocationAction -> { val randomCity = CityDataSource.getRandomCity(action.cities) // TODO: Call fake location api with random location here. val success = DummyDataSource.setLocationMode( LocationMode.RANDOM_LOCATION, randomCity.toRandomLocation() ) if (success) { flowOf( Effect.RandomLocationSelectedEffect Loading @@ -125,6 +172,7 @@ class FakeLocationFeature( } } Action.UseRealLocationAction -> { // TODO: Call turn off fake location api here. val success = DummyDataSource.setLocationMode(LocationMode.REAL_LOCATION) if (success) { flowOf( Loading @@ -137,8 +185,7 @@ class FakeLocationFeature( } } Action.UseSpecificLocationAction -> { val location = DummyDataSource.location.value flowOf(Effect.SpecificLocationSelectedEffect(location.copy(mode = LocationMode.CUSTOM_LOCATION))) flowOf(Effect.SpecificLocationSelectedEffect) } } }, Loading
app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt +163 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes
app/src/main/res/layout/fragment_fake_location.xml +33 −42 Original line number Diff line number Diff line Loading @@ -3,30 +3,30 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:mapbox="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:layout_height="match_parent" android:layout_width="match_parent" > <Toolbar android:background="@color/white" android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:layout_gravity="top|center" android:background="@color/white" android:layout_height="?android:attr/actionBarSize" android:layout_width="match_parent" tools:layout_height="56dp" /> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" android:layout_marginBottom="32dp" android:layout_marginTop="?android:attr/actionBarSize" android:layout_width="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" android:paddingLeft="32dp" android:paddingRight="32dp" Loading @@ -35,9 +35,9 @@ <TextView android:id="@+id/fake_location_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_height="wrap_content" android:layout_width="match_parent" android:paddingTop="16dp" android:text="@string/fake_location_info" android:textColor="@color/black" Loading @@ -45,23 +45,23 @@ /> <TextView android:id="@+id/learn_more_fake_location" android:layout_width="wrap_content" android:layout_height="48dp" android:fontFamily="sans-serif-medium" android:gravity="center_vertical" android:id="@+id/learn_more_fake_location" android:layout_height="48dp" android:layout_width="wrap_content" android:text="@string/learn_more" android:textColor="#007fff" android:textSize="14sp" /> <TextView android:fontFamily="sans-serif-medium" android:id="@+id/my_location_header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="sans-serif-medium" android:paddingTop="16dp" android:layout_width="wrap_content" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="@string/my_location_title" android:textColor="@color/black" android:textSize="14sp" Loading @@ -69,31 +69,31 @@ <RadioGroup android:id="@+id/location_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical" > <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_real_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_real_location" android:textSize="16sp" /> <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_random_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_random_location" android:textSize="16sp" /> <foundation.e.privacycentralapp.common.RightRadioButton android:id="@+id/radio_use_specific_location" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="@string/use_specific_location" android:textSize="16sp" /> Loading @@ -102,53 +102,44 @@ <foundation.e.privacycentralapp.features.location.FakeLocationMapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="240dp" mapbox:mapbox_cameraZoom="15" android:layout_marginTop="32dp" android:layout_marginBottom="32dp" android:layout_marginTop="32dp" android:layout_width="match_parent" mapbox:mapbox_cameraZoom="8" /> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edittext_longitude" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/longitude" android:id="@+id/edittext_longitude" android:layout_height="wrap_content" android:layout_width="match_parent" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:layout_height="wrap_content" android:layout_width="match_parent" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/edittext_latitude" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:hint="@string/latitude" android:id="@+id/edittext_latitude" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:hint="@string/latitude" android:layout_width="match_parent" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal" android:layout_height="wrap_content" android:layout_width="match_parent" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/button_add_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="32dp" android:text="@string/add_location" app:backgroundTint="#007fff" /> </LinearLayout> </androidx.core.widget.NestedScrollView> </FrameLayout> No newline at end of file