make helper method suspend, use different scope in View

This commit is contained in:
David Kaspar
2025-05-14 19:15:16 +02:00
parent d6ee09ecdb
commit 3b5d12b477
2 changed files with 27 additions and 24 deletions
@@ -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 {
@@ -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 ->