update permission request code in SearchStatusesFragment and SFragment, store the argument in a field saved as part of instance state.

This commit is contained in:
Christophe Beyls 2024-04-23 15:24:36 +02:00
parent 99b4629b8c
commit bb6673db59
2 changed files with 95 additions and 46 deletions

View File

@ -21,16 +21,18 @@ import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.getSystemService
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.paging.PagingData import androidx.paging.PagingData
@ -41,7 +43,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
import at.connyduck.calladapter.networkresult.onFailure import at.connyduck.calladapter.networkresult.onFailure
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.compose.ComposeActivity
@ -79,6 +80,34 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
private val searchAdapter private val searchAdapter
get() = super.adapter as SearchStatusesAdapter get() = super.adapter as SearchStatusesAdapter
private var pendingMediaDownloads: List<String>? = null
private val downloadAllMediaPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
pendingMediaDownloads?.let { downloadAllMedia(it) }
} else {
Toast.makeText(
context,
R.string.error_media_download_permission,
Toast.LENGTH_SHORT
).show()
}
pendingMediaDownloads = null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pendingMediaDownloads = savedInstanceState?.getStringArrayList(PENDING_MEDIA_DOWNLOADS_STATE_KEY)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
pendingMediaDownloads?.let {
outState.putStringArrayList(PENDING_MEDIA_DOWNLOADS_STATE_KEY, ArrayList(it))
}
}
override fun createAdapter(): PagingDataAdapter<StatusViewData.Concrete, *> { override fun createAdapter(): PagingDataAdapter<StatusViewData.Concrete, *> {
val preferences = PreferenceManager.getDefaultSharedPreferences( val preferences = PreferenceManager.getDefaultSharedPreferences(
binding.searchRecyclerView.context binding.searchRecyclerView.context
@ -236,10 +265,6 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
} }
} }
companion object {
fun newInstance() = SearchStatusesFragment()
}
private fun reply(status: StatusViewData.Concrete) { private fun reply(status: StatusViewData.Concrete) {
val actionableStatus = status.actionable val actionableStatus = status.actionable
val mentionedUsernames = actionableStatus.mentions.map { it.username } val mentionedUsernames = actionableStatus.mentions.map { it.username }
@ -499,37 +524,31 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
) )
} }
private fun downloadAllMedia(status: Status) { private fun downloadAllMedia(mediaUrls: List<String>) {
Toast.makeText(context, R.string.downloading_media, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.downloading_media, Toast.LENGTH_SHORT).show()
for ((_, url) in status.attachments) { val downloadManager: DownloadManager = requireContext().getSystemService()!!
val uri = Uri.parse(url)
val filename = uri.lastPathSegment
val downloadManager = requireActivity().getSystemService( for (url in mediaUrls) {
Context.DOWNLOAD_SERVICE val uri = Uri.parse(url)
) as DownloadManager
val request = DownloadManager.Request(uri) val request = DownloadManager.Request(uri)
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename) request.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
uri.lastPathSegment
)
downloadManager.enqueue(request) downloadManager.enqueue(request)
} }
} }
private fun requestDownloadAllMedia(status: Status) { private fun requestDownloadAllMedia(status: Status) {
if (status.attachments.isEmpty()) {
return
}
val mediaUrls = status.attachments.map { it.url }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) pendingMediaDownloads = mediaUrls
(activity as BaseActivity).requestPermissions(permissions) { _, grantResults -> downloadAllMediaPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadAllMedia(status)
} else {
Toast.makeText(
context,
R.string.error_media_download_permission,
Toast.LENGTH_SHORT
).show()
}
}
} else { } else {
downloadAllMedia(status) downloadAllMedia(mediaUrls)
} }
} }
@ -628,4 +647,10 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
) )
} }
} }
companion object {
private const val PENDING_MEDIA_DOWNLOADS_STATE_KEY = "pending_media_downloads"
fun newInstance() = SearchStatusesFragment()
}
} }

View File

@ -21,17 +21,19 @@ import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
@ -93,6 +95,22 @@ abstract class SFragment : Fragment(), Injectable {
@Inject @Inject
lateinit var instanceInfoRepository: InstanceInfoRepository lateinit var instanceInfoRepository: InstanceInfoRepository
private var pendingMediaDownloads: List<String>? = null
private val downloadAllMediaPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
pendingMediaDownloads?.let { downloadAllMedia(it) }
} else {
Toast.makeText(
context,
R.string.error_media_download_permission,
Toast.LENGTH_SHORT
).show()
}
pendingMediaDownloads = null
}
override fun startActivity(intent: Intent) { override fun startActivity(intent: Intent) {
requireActivity().startActivityWithSlideInAnimation(intent) requireActivity().startActivityWithSlideInAnimation(intent)
} }
@ -106,6 +124,18 @@ abstract class SFragment : Fragment(), Injectable {
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pendingMediaDownloads = savedInstanceState?.getStringArrayList(PENDING_MEDIA_DOWNLOADS_STATE_KEY)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
pendingMediaDownloads?.let {
outState.putStringArrayList(PENDING_MEDIA_DOWNLOADS_STATE_KEY, ArrayList(it))
}
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@ -522,13 +552,11 @@ abstract class SFragment : Fragment(), Injectable {
} }
} }
private fun downloadAllMedia(status: Status) { private fun downloadAllMedia(mediaUrls: List<String>) {
Toast.makeText(context, R.string.downloading_media, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.downloading_media, Toast.LENGTH_SHORT).show()
val downloadManager = requireActivity().getSystemService( val downloadManager: DownloadManager = requireContext().getSystemService()!!
Context.DOWNLOAD_SERVICE
) as DownloadManager
for ((_, url) in status.attachments) { for (url in mediaUrls) {
val uri = Uri.parse(url) val uri = Uri.parse(url)
downloadManager.enqueue( downloadManager.enqueue(
DownloadManager.Request(uri).apply { DownloadManager.Request(uri).apply {
@ -542,26 +570,22 @@ abstract class SFragment : Fragment(), Injectable {
} }
private fun requestDownloadAllMedia(status: Status) { private fun requestDownloadAllMedia(status: Status) {
if (status.attachments.isEmpty()) {
return
}
val mediaUrls = status.attachments.map { it.url }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) pendingMediaDownloads = mediaUrls
(activity as BaseActivity).requestPermissions(permissions) { _, grantResults -> downloadAllMediaPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadAllMedia(status)
} else {
Toast.makeText(
context,
R.string.error_media_download_permission,
Toast.LENGTH_SHORT
).show()
}
}
} else { } else {
downloadAllMedia(status) downloadAllMedia(mediaUrls)
} }
} }
companion object { companion object {
private const val TAG = "SFragment" private const val TAG = "SFragment"
private const val PENDING_MEDIA_DOWNLOADS_STATE_KEY = "pending_media_downloads"
private fun accountIsInMentions( private fun accountIsInMentions(
account: AccountEntity?, account: AccountEntity?,
mentions: List<Status.Mention> mentions: List<Status.Mention>