Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
android:theme="@style/Theme.App"
android:taskAffinity=".ui.activities.InAppGallery"
android:excludeFromRecents="true"
android:windowSoftInputMode="adjustResize"
android:exported="false"/>

<activity
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/app/grapheneos/camera/CamConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ class CamConfig(private val mActivity: MainActivity) {

const val ENABLE_ZSL = "enable_zsl"

const val MOCK_LOCATION_STATE = "mock_location_state"

const val MOCK_LOCATION_LATITUDE = "mock_location_latitude"
const val MOCK_LOCATION_LONGITUDE = "mock_location_longitude"

// const val IMAGE_FILE_FORMAT = "image_quality"
// const val VIDEO_FILE_FORMAT = "video_quality"
}
Expand Down Expand Up @@ -156,6 +161,11 @@ class CamConfig(private val mActivity: MainActivity) {

const val ENABLE_ZSL = false

const val MOCK_LOCATION_STATE = false

const val MOCK_LOCATION_LATITUDE = 0.0f
const val MOCK_LOCATION_LONGITUDE = 0.0f

// const val IMAGE_FILE_FORMAT = ""
// const val VIDEO_FILE_FORMAT = ""
}
Expand Down Expand Up @@ -555,6 +565,48 @@ class CamConfig(private val mActivity: MainActivity) {
editor.apply()
}

var mockLocationEnabled: Boolean
get() {
return commonPref.getBoolean(
SettingValues.Key.MOCK_LOCATION_STATE,
SettingValues.Default.MOCK_LOCATION_STATE
)
}
set(value) {
val editor = commonPref.edit()
editor.putBoolean(
SettingValues.Key.MOCK_LOCATION_STATE,
value
)
editor.apply()
}

var mockLocationLatitude: Float
get() {
return commonPref.getFloat(
SettingValues.Key.MOCK_LOCATION_LATITUDE,
SettingValues.Default.MOCK_LOCATION_LATITUDE
)
}
set(value) {
val editor = commonPref.edit()
editor.putFloat(SettingValues.Key.MOCK_LOCATION_LATITUDE, value)
editor.apply()
}

var mockLocationLongitude: Float
get() {
return commonPref.getFloat(
SettingValues.Key.MOCK_LOCATION_LONGITUDE,
SettingValues.Default.MOCK_LOCATION_LONGITUDE
)
}
set(value) {
val editor = commonPref.edit()
editor.putFloat(SettingValues.Key.MOCK_LOCATION_LONGITUDE, value)
editor.apply()
}

val isZslSupported : Boolean by lazy {
camera!!.cameraInfo.isZslSupported
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ package app.grapheneos.camera

import android.text.InputFilter
import android.text.Spanned
import app.grapheneos.camera.ui.activities.MoreSettings

class NumInputFilter(private val settings: MoreSettings) : InputFilter {
// Ensures that the field is within the min/max limits for a number type input field
class NumLimitFilter(
val min: Float,
val max: Float,
val onOutOfRange: () -> Unit,
) : InputFilter {

constructor(min: Int, max: Int, onOutOfRange: () -> Unit) : this(min.toFloat(), max.toFloat(), onOutOfRange)

override fun filter(
source: CharSequence,
Expand All @@ -18,25 +24,20 @@ class NumInputFilter(private val settings: MoreSettings) : InputFilter {
val input = (dest.subSequence(0, dstart).toString() + source + dest.subSequence(
dend,
dest.length
)).toInt()
)).toFloat()
if (isInRange(input)) {
return null
} else {
settings.showMessage(settings.getString(
R.string.photo_quality_number_limit, min, max))
this.onOutOfRange()
}
} catch (e: NumberFormatException) {
e.printStackTrace()
return null
}
return ""
}

private fun isInRange(value: Int): Boolean {
return value in min..max
}

companion object {
const val min = 1
const val max = 100
private fun isInRange(value: Float): Boolean {
return value in this.min..this.max
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.app.NotificationManager
import android.content.ClipData
import android.content.ClipboardManager
import android.graphics.Bitmap
import android.location.Location
import android.os.Build
import android.util.Log
import android.view.View
Expand Down Expand Up @@ -77,7 +78,14 @@ class ImageCapturer(val mActivity: MainActivity) {
&& camConfig.saveImageAsPreviewed

if (camConfig.requireLocation) {
val location = (mActivity.applicationContext as App).getLocation()
val location = if (camConfig.mockLocationEnabled) {
val loc = Location("")
loc.latitude = camConfig.mockLocationLatitude.toDouble()
loc.longitude = camConfig.mockLocationLongitude.toDouble()
loc
} else {
(mActivity.applicationContext as App).getLocation()
}
if (location == null) {
mActivity.showMessage(R.string.location_unavailable)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,15 @@ class VideoCapturer(private val mActivity: MainActivity) {

var location: Location? = null
if (camConfig.requireLocation) {
location = (mActivity.applicationContext as App).getLocation()
val location = if (camConfig.mockLocationEnabled) {
val loc = Location("")
loc.latitude = camConfig.mockLocationLatitude.toDouble()
loc.longitude = camConfig.mockLocationLongitude.toDouble()
loc
} else {
(mActivity.applicationContext as App).getLocation()
}

if (location == null) {
mActivity.showMessage(R.string.location_unavailable)
}
Expand Down
123 changes: 103 additions & 20 deletions app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package app.grapheneos.camera.ui.activities

import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Rect
import android.os.Bundle
import android.view.KeyEvent
Expand All @@ -16,12 +15,11 @@ import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import app.grapheneos.camera.CamConfig
import app.grapheneos.camera.CapturedItems
import app.grapheneos.camera.NumInputFilter
import app.grapheneos.camera.NumLimitFilter
import app.grapheneos.camera.R
import app.grapheneos.camera.databinding.MoreSettingsBinding
import app.grapheneos.camera.util.storageLocationToUiString
Expand Down Expand Up @@ -150,9 +148,99 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
pQField.setText(camConfig.photoQuality.toString())
}

pQField.filters = arrayOf(NumInputFilter(this))
pQField.filters = arrayOf(NumLimitFilter(
min = PHOTO_QUALITY_MIN,
max = PHOTO_QUALITY_MAX,
onOutOfRange = {
showMessage(getString(R.string.photo_quality_number_limit, PHOTO_QUALITY_MIN, PHOTO_QUALITY_MAX))
}
))

pQField.onFocusChangeListener = object: View.OnFocusChangeListener {
override fun onFocusChange(v: View, hasFocus: Boolean) {
if (!hasFocus) {
if (pQField.text.isEmpty()) {
camConfig.photoQuality = 0

showMessage(
getString(R.string.photo_quality_was_set_to_auto)
)
} else {
try {
camConfig.photoQuality =
Integer.parseInt(pQField.text.toString())
} catch (exception: Exception) {
camConfig.photoQuality = 0

}
}
}
}
}
pQField.setOnEditorActionListener(this)

val latitudeField = binding.latitudeTextfield
latitudeField.setText(camConfig.mockLocationLatitude.toString())
latitudeField.filters = arrayOf(NumLimitFilter(
min = LATITUDE_MIN,
max = LATITUDE_MAX,
onOutOfRange = {
showMessage(getString(R.string.latitude_number_limit, LATITUDE_MIN, LATITUDE_MAX))
}
))
latitudeField.onFocusChangeListener = object: View.OnFocusChangeListener {
override fun onFocusChange(v: View, hasFocus: Boolean) {
if (!hasFocus) {
if (latitudeField.text?.isEmpty() != false) {
latitudeField.setText(camConfig.mockLocationLatitude.toString())
showMessage(getString(R.string.latitude_number_limit, LATITUDE_MIN, LATITUDE_MAX))
} else {
try {
camConfig.mockLocationLatitude = latitudeField.text.toString().toFloat()
} catch (exception: Exception) {
camConfig.mockLocationLatitude = 0f
showMessage(getString(R.string.latitude_number_limit, LATITUDE_MIN, LATITUDE_MAX))

}
}
}
}
}
latitudeField.setOnEditorActionListener(this)

val longitudeField = binding.longitudeTextfield
longitudeField.setText(camConfig.mockLocationLongitude.toString())
longitudeField.filters = arrayOf(NumLimitFilter(
min = LONGITUDE_MIN.toFloat(),
max = LONGITUDE_MAX.toFloat(),
onOutOfRange = {
showMessage(getString(R.string.longitude_number_limit, LONGITUDE_MIN, LONGITUDE_MAX))
}
))
longitudeField.onFocusChangeListener = object: View.OnFocusChangeListener {
override fun onFocusChange(v: View, hasFocus: Boolean) {
if (!hasFocus) {
if (longitudeField.text?.isEmpty() != false) {
longitudeField.setText(camConfig.mockLocationLongitude.toString())
showMessage(getString(R.string.longitude_number_limit, LONGITUDE_MIN, LONGITUDE_MAX))
} else {
try {
camConfig.mockLocationLongitude = longitudeField.text.toString().toFloat()
} catch (exception: Exception) {
camConfig.mockLocationLongitude = 0f
showMessage(getString(R.string.longitude_number_limit, LONGITUDE_MIN, LONGITUDE_MAX))
}
}
}
}
}
longitudeField.setOnEditorActionListener(this)

binding.mockLocationSettingSwitch.isChecked = camConfig.mockLocationEnabled
binding.mockLocationSettingSwitch.setOnClickListener {
camConfig.mockLocationEnabled = !camConfig.mockLocationEnabled
}

iFField = binding.imageFormatSettingField
iFField.setOnEditorActionListener(this)

Expand Down Expand Up @@ -267,7 +355,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
v.getGlobalVisibleRect(outRect)
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
clearFocus()
dumpData()
// dumpData()
}
}
}
Expand All @@ -287,24 +375,10 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
private fun dumpData() {

// Dump state of photo quality
if (pQField.text.isEmpty()) {
camConfig.photoQuality = 0

showMessage(
getString(R.string.photo_quality_was_set_to_auto)
)
} else {
try {

camConfig.photoQuality =
Integer.parseInt(pQField.text.toString())

} catch (exception: Exception) {
// Dump state of image format

camConfig.photoQuality = 0

}
}

// // Dump state of image format
// camConfig.imageFormat = iFField.text.toString()
Expand Down Expand Up @@ -332,6 +406,15 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
}

companion object {
const val PHOTO_QUALITY_MIN = 1
const val PHOTO_QUALITY_MAX = 100

const val LATITUDE_MIN = -90f
const val LATITUDE_MAX = 90f

const val LONGITUDE_MIN = -180f
const val LONGITUDE_MAX = 180f

private var camConfigId = 0L
private var staticCamConfig: CamConfig? = null

Expand Down
47 changes: 12 additions & 35 deletions app/src/main/res/drawable/location.xml
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false">
<layer-list>
<item>
<shape android:shape="oval">
<solid android:color="?attr/colorSurfaceContainer"/>
<padding
android:left="@dimen/toggle_button_padding"
android:right="@dimen/toggle_button_padding"
android:top="@dimen/toggle_button_padding"
android:bottom="@dimen/toggle_button_padding"/>
</shape>
</item>
<item
android:drawable="@drawable/location_off"/>
</layer-list>
</item>
<item android:state_checked="true">
<layer-list>
<item>
<shape android:shape="oval">
<solid android:color="?attr/colorPrimary"/>
<padding
android:left="@dimen/toggle_button_padding"
android:right="@dimen/toggle_button_padding"
android:top="@dimen/toggle_button_padding"
android:bottom="@dimen/toggle_button_padding"/>
</shape>
</item>
<item
android:drawable="@drawable/location_on"/>
</layer-list>
</item>
</selector>
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">

<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>

</vector>
Loading