|
|
|
|
@ -3,6 +3,7 @@
|
|
|
|
|
|
|
|
|
|
package com.tailscale.ipn
|
|
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
|
import android.content.Intent
|
|
|
|
|
import android.net.Uri
|
|
|
|
|
import android.os.Build
|
|
|
|
|
@ -14,6 +15,7 @@ import androidx.activity.compose.setContent
|
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
|
import androidx.compose.material3.Surface
|
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.core.content.FileProvider
|
|
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
|
|
import com.tailscale.ipn.ui.model.Ipn
|
|
|
|
|
import com.tailscale.ipn.ui.theme.AppTheme
|
|
|
|
|
@ -27,6 +29,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
import kotlinx.coroutines.withContext
|
|
|
|
|
import java.io.File
|
|
|
|
|
|
|
|
|
|
// ShareActivity is the entry point for Taildrop share intents
|
|
|
|
|
class ShareActivity : ComponentActivity() {
|
|
|
|
|
@ -57,11 +60,13 @@ class ShareActivity : ComponentActivity() {
|
|
|
|
|
override fun onNewIntent(intent: Intent) {
|
|
|
|
|
super.onNewIntent(intent)
|
|
|
|
|
setIntent(intent)
|
|
|
|
|
lifecycleScope.launch {
|
|
|
|
|
loadFiles()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Loads the files from the intent.
|
|
|
|
|
fun loadFiles() {
|
|
|
|
|
suspend fun loadFiles() {
|
|
|
|
|
if (intent == null) {
|
|
|
|
|
TSLog.e(TAG, "Share failure - No intent found")
|
|
|
|
|
return
|
|
|
|
|
@ -76,6 +81,13 @@ class ShareActivity : ComponentActivity() {
|
|
|
|
|
// If EXTRA_STREAM is present, get the single URI for that stream
|
|
|
|
|
listOfNotNull(intent.versionSafeGetStreamUri())
|
|
|
|
|
}
|
|
|
|
|
else if (intent.extras?.containsKey(Intent.EXTRA_TEXT) == true) {
|
|
|
|
|
// If EXTRA_TEXT is present, create a temporary file with the text content.
|
|
|
|
|
// This could be any shared text, like a URL or plain text from the clipboard.
|
|
|
|
|
val text = intent.getStringExtra(Intent.EXTRA_TEXT) ?: ""
|
|
|
|
|
val uri = createTemporaryFile(text)
|
|
|
|
|
listOf(uri)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
TSLog.e(TAG, "No extras found in intent - nothing to share")
|
|
|
|
|
emptyList()
|
|
|
|
|
@ -141,3 +153,35 @@ private fun Intent.versionSafeGetStreamUris(): List<Uri> =
|
|
|
|
|
}
|
|
|
|
|
?.filterNotNull()
|
|
|
|
|
?: emptyList()
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a temporary txt file in the app's cache directory with the given content.
|
|
|
|
|
* Then grants temporary read permission to the file using FileProvider and returns its URI.
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun Context.createTemporaryFile(
|
|
|
|
|
content: String,
|
|
|
|
|
dir: File = cacheDir,
|
|
|
|
|
fileName: String = "shared_text_${System.currentTimeMillis()}.txt",
|
|
|
|
|
): Uri {
|
|
|
|
|
// Create temporary file in cache directory
|
|
|
|
|
val tempFile = File(dir, fileName)
|
|
|
|
|
withContext(Dispatchers.IO) {
|
|
|
|
|
tempFile.writeText(content)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get content URI using FileProvider
|
|
|
|
|
val uri = FileProvider.getUriForFile(
|
|
|
|
|
this,
|
|
|
|
|
"${applicationContext.packageName}.fileprovider",
|
|
|
|
|
tempFile
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Grant temporary read permission
|
|
|
|
|
grantUriPermission(
|
|
|
|
|
packageName,
|
|
|
|
|
uri,
|
|
|
|
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return uri
|
|
|
|
|
}
|