make helper method suspend, use different scope in View
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2024 Vitor Pamplona
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
@@ -25,6 +25,8 @@ import android.net.Uri
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import com.vitorpamplona.amethyst.Amethyst
|
import com.vitorpamplona.amethyst.Amethyst
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -41,25 +43,26 @@ object ShareHelper {
|
|||||||
private val WEBP_HEADER_END = "WEBP".toByteArray()
|
private val WEBP_HEADER_END = "WEBP".toByteArray()
|
||||||
private val GIF_MAGIC = "GIF8".toByteArray()
|
private val GIF_MAGIC = "GIF8".toByteArray()
|
||||||
|
|
||||||
fun getSharableUriFromUrl(
|
suspend fun getSharableUriFromUrl(
|
||||||
context: Context,
|
context: Context,
|
||||||
imageUrl: String,
|
imageUrl: String,
|
||||||
): Pair<Uri, String> {
|
): Pair<Uri, String> =
|
||||||
// Safely get snapshot and file
|
withContext(Dispatchers.IO) {
|
||||||
Amethyst.instance.diskCache.openSnapshot(imageUrl)?.use { snapshot ->
|
// Safely get snapshot and file
|
||||||
val file = snapshot.data.toFile()
|
Amethyst.instance.diskCache.openSnapshot(imageUrl)?.use { snapshot ->
|
||||||
|
val file = snapshot.data.toFile()
|
||||||
|
|
||||||
// Determine file extension and prepare sharable file
|
// Determine file extension and prepare sharable file
|
||||||
val fileExtension = getImageExtension(file)
|
val fileExtension = getImageExtension(file)
|
||||||
val fileCopy = prepareSharableFile(context, file, fileExtension)
|
val fileCopy = prepareSharableFile(context, file, fileExtension)
|
||||||
|
|
||||||
// Return sharable uri
|
// Return sharable uri
|
||||||
return Pair(
|
return@use Pair(
|
||||||
FileProvider.getUriForFile(context, "${context.packageName}.provider", fileCopy),
|
FileProvider.getUriForFile(context, "${context.packageName}.provider", fileCopy),
|
||||||
fileExtension,
|
fileExtension,
|
||||||
)
|
)
|
||||||
} ?: throw IOException("Unable to open snapshot for: $imageUrl")
|
} ?: throw IOException("Unable to open snapshot for: $imageUrl")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getImageExtension(file: File): String =
|
private fun getImageExtension(file: File): String =
|
||||||
try {
|
try {
|
||||||
|
|||||||
+8
-8
@@ -49,6 +49,7 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -104,7 +105,6 @@ import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
|||||||
import com.vitorpamplona.quartz.utils.sha256.sha256
|
import com.vitorpamplona.quartz.utils.sha256.sha256
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -716,6 +716,8 @@ fun ShareImageAction(
|
|||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
content: BaseMediaContent? = null,
|
content: BaseMediaContent? = null,
|
||||||
) {
|
) {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = popupExpanded.value,
|
expanded = popupExpanded.value,
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
@@ -767,7 +769,7 @@ fun ShareImageAction(
|
|||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringRes(R.string.share_image)) },
|
text = { Text(stringRes(R.string.share_image)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
shareImageFile(context, videoUri, mimeType)
|
scope.launch { shareImageFile(context, videoUri, mimeType) }
|
||||||
onDismiss()
|
onDismiss()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -778,7 +780,7 @@ fun ShareImageAction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shareImageFile(
|
private suspend fun shareImageFile(
|
||||||
context: Context,
|
context: Context,
|
||||||
videoUri: String,
|
videoUri: String,
|
||||||
mimeType: String?,
|
mimeType: String?,
|
||||||
@@ -796,13 +798,11 @@ private fun shareImageFile(
|
|||||||
putExtra(Intent.EXTRA_STREAM, uri)
|
putExtra(Intent.EXTRA_STREAM, uri)
|
||||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
}
|
}
|
||||||
// TODO is this the right scope to avoid leaks?
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
context.startActivity(Intent.createChooser(shareIntent, null))
|
||||||
context.startActivity(Intent.createChooser(shareIntent, null))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun verifyHash(content: MediaUrlContent): Boolean? {
|
private fun verifyHash(content: MediaUrlContent): Boolean? {
|
||||||
if (content.hash == null) return null
|
if (content.hash == null) return null
|
||||||
|
|
||||||
Amethyst.instance.diskCache.openSnapshot(content.url)?.use { snapshot ->
|
Amethyst.instance.diskCache.openSnapshot(content.url)?.use { snapshot ->
|
||||||
|
|||||||
Reference in New Issue
Block a user