Skip to content

Commit

Permalink
Simplify storage access
Browse files Browse the repository at this point in the history
Closes #40

As a side effect, the following issues were also addressed:

Closes #24

Closes #60

Closes #74
  • Loading branch information
naveensingh committed Jan 7, 2025
1 parent 060ba08 commit 9f25538
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 491 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ import org.fossify.voicerecorder.BuildConfig
import org.fossify.voicerecorder.R
import org.fossify.voicerecorder.adapters.ViewPagerAdapter
import org.fossify.voicerecorder.databinding.ActivityMainBinding
import org.fossify.voicerecorder.extensions.checkRecycleBinItems
import org.fossify.voicerecorder.extensions.config
import org.fossify.voicerecorder.extensions.deleteExpiredTrashedRecordings
import org.fossify.voicerecorder.extensions.ensureStoragePermission
import org.fossify.voicerecorder.helpers.STOP_AMPLITUDE_UPDATE
import org.fossify.voicerecorder.models.Events
import org.fossify.voicerecorder.services.RecorderService
Expand Down Expand Up @@ -65,7 +66,7 @@ class MainActivity : SimpleActivity() {
}

if (savedInstanceState == null) {
checkRecycleBinItems()
deleteExpiredTrashedRecordings()
}

handlePermission(PERMISSION_RECORD_AUDIO) {
Expand Down Expand Up @@ -172,12 +173,20 @@ class MainActivity : SimpleActivity() {

private fun tryInitVoiceRecorder() {
if (isRPlus()) {
setupViewPager()
ensureStoragePermission { granted ->
if (granted) {
setupViewPager()
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
}
} else {
handlePermission(PERMISSION_WRITE_STORAGE) {
if (it) {
setupViewPager()
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import android.media.MediaRecorder
import android.os.Bundle
import org.fossify.commons.dialogs.ChangeDateTimeFormatDialog
import org.fossify.commons.dialogs.ConfirmationDialog
import org.fossify.commons.dialogs.FeatureLockedDialog
import org.fossify.commons.dialogs.FilePickerDialog
import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.addLockedLabelIfNeeded
import org.fossify.commons.extensions.beGone
Expand All @@ -31,8 +29,9 @@ import org.fossify.commons.models.RadioItem
import org.fossify.voicerecorder.R
import org.fossify.voicerecorder.databinding.ActivitySettingsBinding
import org.fossify.voicerecorder.extensions.config
import org.fossify.voicerecorder.extensions.emptyTheRecycleBin
import org.fossify.voicerecorder.extensions.deleteTrashedRecordings
import org.fossify.voicerecorder.extensions.getAllRecordings
import org.fossify.voicerecorder.extensions.launchFilePickerDialog
import org.fossify.voicerecorder.helpers.BITRATES
import org.fossify.voicerecorder.helpers.EXTENSION_M4A
import org.fossify.voicerecorder.helpers.EXTENSION_MP3
Expand Down Expand Up @@ -158,27 +157,8 @@ class SettingsActivity : SimpleActivity() {
addLockedLabelIfNeeded(R.string.save_recordings_in)
binding.settingsSaveRecordings.text = humanizePath(config.saveRecordingsFolder)
binding.settingsSaveRecordingsHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
FilePickerDialog(this, config.saveRecordingsFolder, false, showFAB = true) {
val path = it
handleSAFDialog(path) { grantedSAF ->
if (!grantedSAF) {
return@handleSAFDialog
}

handleSAFDialogSdk30(path) { grantedSAF30 ->
if (!grantedSAF30) {
return@handleSAFDialogSdk30
}

config.saveRecordingsFolder = path
binding.settingsSaveRecordings.text =
humanizePath(config.saveRecordingsFolder)
}
}
}
} else {
FeatureLockedDialog(this) { }
launchFilePickerDialog {
binding.settingsSaveRecordings.text = humanizePath(config.saveRecordingsFolder)
}
}
}
Expand Down Expand Up @@ -272,7 +252,7 @@ class SettingsActivity : SimpleActivity() {
negative = org.fossify.commons.R.string.no
) {
ensureBackgroundThread {
emptyTheRecycleBin()
deleteTrashedRecordings()
runOnUiThread {
recycleBinContentSize = 0
binding.settingsEmptyRecycleBinSize.text = 0.formatSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import org.fossify.commons.extensions.openPathIntent
import org.fossify.commons.extensions.setupViewBackground
import org.fossify.commons.extensions.sharePathsIntent
import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.helpers.isQPlus
import org.fossify.commons.views.MyRecyclerView
import org.fossify.voicerecorder.BuildConfig
import org.fossify.voicerecorder.R
Expand All @@ -29,8 +28,7 @@ import org.fossify.voicerecorder.dialogs.DeleteConfirmationDialog
import org.fossify.voicerecorder.dialogs.RenameRecordingDialog
import org.fossify.voicerecorder.extensions.config
import org.fossify.voicerecorder.extensions.deleteRecordings
import org.fossify.voicerecorder.extensions.moveRecordingsToRecycleBin
import org.fossify.voicerecorder.helpers.getAudioFileContentUri
import org.fossify.voicerecorder.extensions.trashRecordings
import org.fossify.voicerecorder.interfaces.RefreshRecordingsListener
import org.fossify.voicerecorder.models.Events
import org.fossify.voicerecorder.models.Recording
Expand Down Expand Up @@ -133,23 +131,13 @@ class RecordingsAdapter(

private fun openRecordingWith() {
val recording = getItemWithKey(selectedKeys.first()) ?: return
val path = if (isQPlus()) {
getAudioFileContentUri(recording.id.toLong()).toString()
} else {
recording.path
}

val path = recording.path
activity.openPathIntent(path, false, BuildConfig.APPLICATION_ID, "audio/*")
}

private fun shareRecordings() {
val selectedItems = getSelectedItems()
val paths = selectedItems.map {
it.path.ifEmpty {
getAudioFileContentUri(it.id.toLong()).toString()
}
}

val paths = selectedItems.map { it.path }
activity.sharePathsIntent(paths, BuildConfig.APPLICATION_ID)
}

Expand Down Expand Up @@ -177,15 +165,15 @@ class RecordingsAdapter(
ensureBackgroundThread {
val toRecycleBin = !skipRecycleBin && activity.config.useRecycleBin
if (toRecycleBin) {
moveMediaStoreRecordingsToRecycleBin()
trashRecordings()
} else {
deleteMediaStoreRecordings()
deleteRecordings()
}
}
}
}

private fun deleteMediaStoreRecordings() {
private fun deleteRecordings() {
if (selectedKeys.isEmpty()) {
return
}
Expand All @@ -203,7 +191,7 @@ class RecordingsAdapter(
}
}

private fun moveMediaStoreRecordingsToRecycleBin() {
private fun trashRecordings() {
if (selectedKeys.isEmpty()) {
return
}
Expand All @@ -214,7 +202,7 @@ class RecordingsAdapter(

val positions = getSelectedItemPositions()

activity.moveRecordingsToRecycleBin(recordingsToRemove) { success ->
activity.trashRecordings(recordingsToRemove) { success ->
if (success) {
doDeleteAnimation(oldRecordingIndex, recordingsToRemove, positions)
EventBus.getDefault().post(Events.RecordingTrashUpdated())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.fossify.voicerecorder.dialogs

import android.content.ContentValues
import android.provider.MediaStore.Audio.Media
import androidx.appcompat.app.AlertDialog
import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.extensions.getAlertDialogBuilder
Expand All @@ -19,7 +17,6 @@ import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.helpers.isRPlus
import org.fossify.voicerecorder.databinding.DialogRenameRecordingBinding
import org.fossify.voicerecorder.extensions.config
import org.fossify.voicerecorder.helpers.getAudioFileContentUri
import org.fossify.voicerecorder.models.Events
import org.fossify.voicerecorder.models.Recording
import org.greenrobot.eventbus.EventBus
Expand Down Expand Up @@ -60,9 +57,9 @@ class RenameRecordingDialog(

ensureBackgroundThread {
if (isRPlus()) {
updateMediaStoreTitle(recording, newTitle)
renameRecording(recording, newTitle)
} else {
updateLegacyFilename(recording, newTitle)
renameRecordingLegacy(recording, newTitle)
}

activity.runOnUiThread {
Expand All @@ -75,40 +72,25 @@ class RenameRecordingDialog(
}
}

private fun updateMediaStoreTitle(recording: Recording, newTitle: String) {
private fun renameRecording(recording: Recording, newTitle: String) {
val oldExtension = recording.title.getFilenameExtension()
val newDisplayName = "${newTitle.removeSuffix(".$oldExtension")}.$oldExtension"

val values = ContentValues().apply {
put(Media.TITLE, newTitle.substringAfterLast('.'))
put(Media.DISPLAY_NAME, newDisplayName)
}

// if the old way of renaming fails, try the new SDK 30 one on Android 11+
try {
activity.contentResolver.update(
getAudioFileContentUri(recording.id.toLong()),
values,
null,
null
)
} catch (e: Exception) {
try {
val path = "${activity.config.saveRecordingsFolder}/${recording.title}"
val newPath = "${path.getParentPath()}/$newDisplayName"
activity.handleSAFDialogSdk30(path) {
val success = activity.renameDocumentSdk30(path, newPath)
if (success) {
EventBus.getDefault().post(Events.RecordingCompleted())
}
val path = "${activity.config.saveRecordingsFolder}/${recording.title}"
val newPath = "${path.getParentPath()}/$newDisplayName"
activity.handleSAFDialogSdk30(path) {
val success = activity.renameDocumentSdk30(path, newPath)
if (success) {
EventBus.getDefault().post(Events.RecordingCompleted())
}
} catch (e: Exception) {
activity.showErrorToast(e)
}
} catch (e: Exception) {
activity.showErrorToast(e)
}
}

private fun updateLegacyFilename(recording: Recording, newTitle: String) {
private fun renameRecordingLegacy(recording: Recording, newTitle: String) {
val oldExtension = recording.title.getFilenameExtension()
val oldPath = recording.path
val newFilename = "${newTitle.removeSuffix(".$oldExtension")}.$oldExtension"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.fossify.voicerecorder.dialogs

import androidx.appcompat.app.AlertDialog
import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.databinding.DialogMessageBinding
import org.fossify.commons.extensions.getAlertDialogBuilder
import org.fossify.commons.extensions.setupDialogStuff
import org.fossify.voicerecorder.R

class StoragePermissionDialog(
private val activity: BaseSimpleActivity,
private val callback: (result: Boolean) -> Unit
) {
private var dialog: AlertDialog? = null

init {
val view = DialogMessageBinding.inflate(activity.layoutInflater, null, false)
view.message.text = activity.getString(R.string.confirm_recording_folder)

activity.getAlertDialogBuilder()
.setPositiveButton(org.fossify.commons.R.string.ok) { _, _ ->
callback(true)
}
.apply {
activity.setupDialogStuff(
view = view.root,
dialog = this,
cancelOnTouchOutside = false,
) { alertDialog ->
dialog = alertDialog
}
}
}
}
Loading

0 comments on commit 9f25538

Please sign in to comment.