diff --git a/app/src/main/java/app/grapheneos/camera/CamConfig.kt b/app/src/main/java/app/grapheneos/camera/CamConfig.kt
index 128205f5..224a645c 100644
--- a/app/src/main/java/app/grapheneos/camera/CamConfig.kt
+++ b/app/src/main/java/app/grapheneos/camera/CamConfig.kt
@@ -111,6 +111,10 @@ class CamConfig(private val mActivity: MainActivity) {
const val ENABLE_ZSL = "enable_zsl"
+ const val SEPARATE_VIDEO_STORAGE = "separate_video_storage"
+
+ const val VIDEO_STORAGE_LOCATION = "video_storage_location"
+
// const val IMAGE_FILE_FORMAT = "image_quality"
// const val VIDEO_FILE_FORMAT = "video_quality"
}
@@ -156,6 +160,8 @@ class CamConfig(private val mActivity: MainActivity) {
const val ENABLE_ZSL = false
+ const val SEPARATE_VIDEO_STORAGE = false
+
// const val IMAGE_FILE_FORMAT = ""
// const val VIDEO_FILE_FORMAT = ""
}
@@ -510,6 +516,40 @@ class CamConfig(private val mActivity: MainActivity) {
editor.apply()
}
+ var videoStorageLocation: String
+ get() {
+ return commonPref.getString(
+ SettingValues.Key.VIDEO_STORAGE_LOCATION,
+ SettingValues.Default.STORAGE_LOCATION
+ )!!
+ }
+ set(value) {
+ val cur = videoStorageLocation
+ if (cur != SettingValues.Default.STORAGE_LOCATION) {
+ CapturedItems.savePreviousSafTree(Uri.parse(cur), commonPref)
+ }
+
+ val editor = commonPref.edit()
+ editor.putString(SettingValues.Key.VIDEO_STORAGE_LOCATION, value)
+ editor.apply()
+ }
+
+ var separateVideoStorage: Boolean
+ get() {
+ return commonPref.getBoolean(
+ SettingValues.Key.SEPARATE_VIDEO_STORAGE,
+ SettingValues.Default.SEPARATE_VIDEO_STORAGE
+ )
+ }
+ set(value) {
+ val editor = commonPref.edit()
+ editor.putBoolean(
+ SettingValues.Key.SEPARATE_VIDEO_STORAGE,
+ value
+ )
+ editor.apply()
+ }
+
var photoQuality: Int
get() {
return commonPref.getInt(
@@ -1545,9 +1585,13 @@ class CamConfig(private val mActivity: MainActivity) {
dialog.showIgnoringShortEdgeMode()
}
- fun onStorageLocationNotFound() {
- // Reverting back to DEFAULT_MEDIA_STORE_CAPTURE_PATH
- storageLocation = SettingValues.Default.STORAGE_LOCATION
+ fun onStorageLocationNotFound(inVideoMode: Boolean = false) {
+ // Reverting back to default path
+ if (inVideoMode && separateVideoStorage) {
+ videoStorageLocation = SettingValues.Default.STORAGE_LOCATION
+ } else {
+ storageLocation = SettingValues.Default.STORAGE_LOCATION
+ }
val builder = MaterialAlertDialogBuilder(mActivity)
.setTitle(R.string.folder_not_found)
diff --git a/app/src/main/java/app/grapheneos/camera/capturer/VideoCapturer.kt b/app/src/main/java/app/grapheneos/camera/capturer/VideoCapturer.kt
index 6a505d0c..8f7fd373 100644
--- a/app/src/main/java/app/grapheneos/camera/capturer/VideoCapturer.kt
+++ b/app/src/main/java/app/grapheneos/camera/capturer/VideoCapturer.kt
@@ -109,7 +109,11 @@ class VideoCapturer(private val mActivity: MainActivity) {
uri = ctx.outputUri
shouldAddToGallery = false
} else {
- val storageLocation = camConfig.storageLocation
+ val storageLocation = if (camConfig.separateVideoStorage) {
+ camConfig.videoStorageLocation
+ } else {
+ camConfig.storageLocation
+ }
if (storageLocation == CamConfig.SettingValues.Default.STORAGE_LOCATION) {
val contentValues = ContentValues().apply {
@@ -177,7 +181,7 @@ class VideoCapturer(private val mActivity: MainActivity) {
} catch (exception: Exception) {
val foreignUri = ctx is VideoCaptureActivity && ctx.isOutputUriAvailable()
if (!foreignUri) {
- camConfig.onStorageLocationNotFound()
+ camConfig.onStorageLocationNotFound(inVideoMode = true)
}
ctx.showMessage(R.string.unable_to_access_output_file)
isRecording = false
diff --git a/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt b/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt
index 18b228fb..cec2e074 100644
--- a/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt
+++ b/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt
@@ -36,7 +36,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
private lateinit var sLField: EditText
- private lateinit var rSLocation: Button
+ private lateinit var vSLField: EditText
private lateinit var rootView: View
@@ -44,9 +44,10 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
private lateinit var iFField: EditText
private lateinit var vFField: EditText
- private val dirPickerHandler = registerForActivityResult(
+ private val defaultStorageDirPicker = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
- ) {
+ ) { it ->
+
val intent = it.data
val uri = intent?.data?.let {
if (it.toString().contains(CapturedItems.SAF_TREE_SEPARATOR)) {
@@ -60,9 +61,9 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
val uriString = uri.toString()
- camConfig.storageLocation = uriString
-
val uiString = storageLocationToUiString(this, uriString)
+
+ camConfig.storageLocation = uriString
sLField.setText(uiString)
showMessage(getString(R.string.storage_location_updated, uiString))
@@ -72,6 +73,35 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
}
}
+ private val videoStorageDirPicker = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { it ->
+
+ val intent = it.data
+
+ val uri = intent?.data?.let {
+ if (it.toString().contains(CapturedItems.SAF_TREE_SEPARATOR)) {
+ null
+ } else {
+ it
+ }
+ }
+
+ if (uri != null) {
+ contentResolver.takePersistableUriPermission(uri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+
+ val uriString = uri.toString()
+ val uiString = storageLocationToUiString(this, uriString)
+
+ camConfig.videoStorageLocation = uriString
+ vSLField.setText(uiString)
+
+ showMessage(getString(R.string.storage_location_updated, uiString))
+ } else {
+ showMessage(getString(R.string.no_directory_selected))
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -113,35 +143,48 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
sLField.setText(storageLocationToUiString(this, camConfig.storageLocation))
sLField.setOnClickListener {
- val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- dirPickerHandler.launch(Intent.createChooser(i, getString(R.string.choose_storage_location)))
+ val dirPickerIntent = Intent.createChooser(
+ Intent(Intent.ACTION_OPEN_DOCUMENT_TREE),
+ getString(R.string.choose_storage_location)
+ )
+ defaultStorageDirPicker.launch(dirPickerIntent)
}
- snackBar = Snackbar.make(rootView, "", Snackbar.LENGTH_LONG)
+ vSLField = binding.videoStorageLocationField
- rSLocation = binding.refreshStorageLocation
- rSLocation.setOnClickListener {
+ vSLField.setText(storageLocationToUiString(this, camConfig.videoStorageLocation))
- val dialog = MaterialAlertDialogBuilder(this)
+ vSLField.setOnClickListener {
+ val dirPickerIntent = Intent.createChooser(
+ Intent(Intent.ACTION_OPEN_DOCUMENT_TREE),
+ getString(R.string.choose_storage_location)
+ )
+ videoStorageDirPicker.launch(dirPickerIntent)
+ }
- dialog.setTitle(R.string.are_you_sure)
+ binding.videoStorageSettingToggle.isChecked = camConfig.separateVideoStorage
- dialog.setMessage(R.string.revert_to_default_directory)
+ binding.videoStorageSettingToggle.setOnClickListener {
+ binding.videoStorageSettingToggle.isChecked.let {
+ camConfig.separateVideoStorage = it
+ vSLField.isEnabled = it
+ binding.refreshVideoStorageLocation.isEnabled = it
+ }
+ }
- dialog.setPositiveButton(R.string.yes) { _, _ ->
- val defaultLocation = CamConfig.SettingValues.Default.STORAGE_LOCATION
+ if (!camConfig.separateVideoStorage) {
+ vSLField.isEnabled = false
+ binding.refreshVideoStorageLocation.isEnabled = false
+ }
- if (camConfig.storageLocation != defaultLocation) {
- showMessage(getString(R.string.reverted_to_default_directory))
- camConfig.storageLocation = defaultLocation
- sLField.setText(storageLocationToUiString(this, defaultLocation))
- } else {
- showMessage(getString(R.string.already_using_default_directory))
- }
- }
+ snackBar = Snackbar.make(rootView, "", Snackbar.LENGTH_LONG)
+
+ binding.refreshStorageLocation.setOnClickListener {
+ promptUserToResetStorageLocation()
+ }
- dialog.setNegativeButton(R.string.no, null)
- dialog.show()
+ binding.refreshVideoStorageLocation.setOnClickListener {
+ promptUserToResetStorageLocation(forVideo = true)
}
pQField = binding.photoQuality
@@ -313,6 +356,41 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
// camConfig.videoFormat = vFField.text.toString()
}
+ private fun promptUserToResetStorageLocation(forVideo: Boolean = false) {
+ val dialog = MaterialAlertDialogBuilder(this)
+
+ dialog.setTitle(R.string.are_you_sure)
+
+ dialog.setMessage(R.string.revert_to_default_directory)
+
+ dialog.setPositiveButton(R.string.yes) { _, _ ->
+ val defaultLocation = CamConfig.SettingValues.Default.STORAGE_LOCATION
+ val currentLocation = if (forVideo) {
+ camConfig.videoStorageLocation
+ } else {
+ camConfig.storageLocation
+ }
+
+ if (currentLocation != defaultLocation) {
+ showMessage(getString(R.string.reverted_to_default_directory))
+
+ if (forVideo) {
+ camConfig.videoStorageLocation = defaultLocation
+ vSLField.setText(storageLocationToUiString(this, defaultLocation))
+ } else {
+ camConfig.storageLocation = defaultLocation
+ sLField.setText(storageLocationToUiString(this, defaultLocation))
+ }
+ } else {
+ showMessage(getString(R.string.already_using_default_directory))
+ }
+ }
+
+ dialog.setNegativeButton(R.string.no, null)
+ dialog.show()
+
+ }
+
override fun onEditorAction(p0: TextView?, id: Int, p2: KeyEvent?): Boolean {
return if (id == EditorInfo.IME_ACTION_DONE) {
clearFocus()
diff --git a/app/src/main/res/drawable/video_storage_icon.xml b/app/src/main/res/drawable/video_storage_icon.xml
new file mode 100644
index 00000000..a64074c2
--- /dev/null
+++ b/app/src/main/res/drawable/video_storage_icon.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/more_settings.xml b/app/src/main/res/layout/more_settings.xml
index c3b8117f..64ff5acd 100644
--- a/app/src/main/res/layout/more_settings.xml
+++ b/app/src/main/res/layout/more_settings.xml
@@ -547,11 +547,67 @@
android:id="@+id/storage_location_icon"
android:layout_width="48dp"
android:layout_height="48dp"
- android:contentDescription="@string/save_image_as_previewed"
+ android:contentDescription="@string/storage_location"
android:paddingStart="4dp"
android:paddingEnd="8dp"
android:src="@drawable/storage" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"
+ android:layout_marginEnd="5dp"
+ android:layout_marginTop="6dp"
+ android:padding="3dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9aa6ae1e..d70715b5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -193,4 +193,7 @@
The video\'s audio recording has been muted
The video\'s audio recording has been unmuted
+
+ Video Storage Location
+ When enabled, stores the video in the below specified location over the above default storage location.