Merge remote-tracking branch 'origin/master' into lame-license

# Conflicts:
#	app/build.gradle
This commit is contained in:
Pavel Poley 2022-06-15 13:12:54 +03:00
commit 9b0d4f474e
5 changed files with 99 additions and 39 deletions

View File

@ -62,7 +62,7 @@ android {
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:bea5638bd5'
implementation 'com.github.SimpleMobileTools:Simple-Commons:d100d21180'
implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'com.github.Armen101:AudioRecordView:1.0.4'
implementation 'androidx.documentfile:documentfile:1.0.1'

View File

@ -1,16 +1,22 @@
package com.simplemobiletools.voicerecorder.adapters
import android.content.ContentUris
import android.content.Context
import android.net.Uri
import android.provider.MediaStore
import android.provider.MediaStore.Audio.Media
import android.view.*
import android.widget.PopupMenu
import android.widget.TextView
import androidx.core.net.toUri
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.commons.models.FileDirItem
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.voicerecorder.BuildConfig
import com.simplemobiletools.voicerecorder.R
@ -151,19 +157,37 @@ class RecordingsAdapter(
val recordingsToRemove = recordings.filter { selectedKeys.contains(it.id) } as ArrayList<Recording>
val positions = getSelectedItemPositions()
if (isQPlus()) {
recordingsToRemove.forEach {
val uri = Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val selection = "${Media._ID} = ?"
val selectionArgs = arrayOf(it.id.toString())
activity.contentResolver.delete(uri, selection, selectionArgs)
when {
isRPlus() -> {
val fileUris = recordingsToRemove.map { recording ->
"${Media.EXTERNAL_CONTENT_URI}/${recording.id.toLong()}".toUri()
}
activity.deleteSDK30Uris(fileUris) { success ->
if (success) {
doDeleteAnimation(oldRecordingIndex, recordingsToRemove, positions)
}
}
}
} else {
recordingsToRemove.forEach {
activity.deleteFile(File(it.path).toFileDirItem(activity))
isQPlus() -> {
recordingsToRemove.forEach {
val uri = Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val selection = "${Media._ID} = ?"
val selectionArgs = arrayOf(it.id.toString())
activity.contentResolver.delete(uri, selection, selectionArgs)
}
doDeleteAnimation(oldRecordingIndex, recordingsToRemove, positions)
}
else -> {
recordingsToRemove.forEach {
activity.deleteFile(File(it.path).toFileDirItem(activity))
}
doDeleteAnimation(oldRecordingIndex, recordingsToRemove, positions)
}
}
}
private fun doDeleteAnimation(oldRecordingIndex: Int, recordingsToRemove: ArrayList<Recording>, positions: ArrayList<Int>) {
recordings.removeAll(recordingsToRemove)
activity.runOnUiThread {
if (recordings.isEmpty()) {
@ -180,6 +204,25 @@ class RecordingsAdapter(
}
}
fun Context.getFileUrisFromFileDirItems2(fileDirItems: List<FileDirItem>): Pair<java.util.ArrayList<String>, java.util.ArrayList<Uri>> {
val fileUris = java.util.ArrayList<Uri>()
val successfulFilePaths = java.util.ArrayList<String>()
val allIds = getMediaStoreIds(this)
val filePaths = fileDirItems.map { it.path }
filePaths.forEach { path ->
for ((filePath, mediaStoreId) in allIds) {
if (filePath.lowercase() == path.lowercase()) {
val baseUri = getFileUri(filePath)
val uri = ContentUris.withAppendedId(baseUri, mediaStoreId)
fileUris.add(uri)
successfulFilePaths.add(path)
}
}
}
return Pair(successfulFilePaths, fileUris)
}
fun updateCurrentRecording(newId: Int) {
val oldId = currRecordingId
currRecordingId = newId

View File

@ -8,9 +8,12 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.dialog_rename_recording.view.*
import org.greenrobot.eventbus.EventBus
import java.io.File
class RenameRecordingDialog(val activity: BaseSimpleActivity, val recording: Recording, val callback: () -> Unit) {
@ -63,10 +66,22 @@ class RenameRecordingDialog(val activity: BaseSimpleActivity, val recording: Rec
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) {
activity.showErrorToast(e)
} catch (e: SecurityException) {
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())
}
}
} catch (e: Exception) {
activity.showErrorToast(e)
}
}
}

View File

@ -16,6 +16,7 @@ import android.provider.MediaStore.Audio.Media
import android.util.AttributeSet
import android.widget.SeekBar
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.voicerecorder.R
@ -32,7 +33,6 @@ import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.roundToLong
class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshRecordingsListener {
@ -136,33 +136,37 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
private fun setupAdapter() {
val recordings = getRecordings()
ensureBackgroundThread {
val recordings = getRecordings()
recordings_fastscroller.beVisibleIf(recordings.isNotEmpty())
recordings_placeholder.beVisibleIf(recordings.isEmpty())
if (recordings.isEmpty()) {
val stringId = if (isQPlus()) R.string.no_recordings_found else R.string.no_recordings_in_folder_found
recordings_placeholder.text = context.getString(stringId)
resetProgress(null)
player?.stop()
}
val adapter = getRecordingsAdapter()
if (adapter == null) {
RecordingsAdapter(context as SimpleActivity, recordings, this, recordings_list) {
playRecording(it as Recording, true)
if (playedRecordingIDs.isEmpty() || playedRecordingIDs.peek() != it.id) {
playedRecordingIDs.push(it.id)
Handler(Looper.getMainLooper()).post {
recordings_fastscroller.beVisibleIf(recordings.isNotEmpty())
recordings_placeholder.beVisibleIf(recordings.isEmpty())
if (recordings.isEmpty()) {
val stringId = if (isQPlus()) R.string.no_recordings_found else R.string.no_recordings_in_folder_found
recordings_placeholder.text = context.getString(stringId)
resetProgress(null)
player?.stop()
}
}.apply {
recordings_list.adapter = this
}
if (context.areSystemAnimationsEnabled) {
recordings_list.scheduleLayoutAnimation()
val adapter = getRecordingsAdapter()
if (adapter == null) {
RecordingsAdapter(context as SimpleActivity, recordings, this, recordings_list) {
playRecording(it as Recording, true)
if (playedRecordingIDs.isEmpty() || playedRecordingIDs.peek() != it.id) {
playedRecordingIDs.push(it.id)
}
}.apply {
recordings_list.adapter = this
}
if (context.areSystemAnimationsEnabled) {
recordings_list.scheduleLayoutAnimation()
}
} else {
adapter.updateItems(recordings)
}
}
} else {
adapter.updateItems(recordings)
}
}

View File

@ -13,9 +13,7 @@ import android.provider.MediaStore
import android.provider.MediaStore.Audio.Media
import androidx.core.app.NotificationCompat
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.SplashActivity
import com.simplemobiletools.voicerecorder.extensions.config