From b91de1de56e81a92b8144571bb069e92aaeed1cb Mon Sep 17 00:00:00 2001
From: Azalea <22280294+hykilpikonna@users.noreply.github.com>
Date: Sun, 26 Oct 2025 23:37:54 +0800
Subject: [PATCH] [+] Drop images
---
android/app/src/main/AndroidManifest.xml | 5 +
.../src/main/java/aza/instant/MainActivity.kt | 147 ++++++++++++------
2 files changed, 105 insertions(+), 47 deletions(-)
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 91d4909..e6f5fcb 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -26,6 +26,11 @@
+
+
+
+
+
diff --git a/android/app/src/main/java/aza/instant/MainActivity.kt b/android/app/src/main/java/aza/instant/MainActivity.kt
index 3385b83..d70faef 100644
--- a/android/app/src/main/java/aza/instant/MainActivity.kt
+++ b/android/app/src/main/java/aza/instant/MainActivity.kt
@@ -1,12 +1,15 @@
package aza.instant
import android.Manifest
+import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
-import android.graphics.Bitmap
import android.graphics.Picture
import android.media.MediaScannerConnection
+import android.net.Uri
+import android.os.Build
import android.os.Bundle
+import android.provider.OpenableColumns
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -51,20 +54,38 @@ import java.io.File
import java.io.InputStreamReader
class MainActivity : ComponentActivity() {
+ private var sharedImageUri by mutableStateOf(null)
+ private var isUriHandled = false
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ handleIntent(intent)
+
setContent {
ProjectInstantTheme {
Scaffold(modifier = Modifier.fillMaxSize()) {
- FileListerScreen(modifier = Modifier.padding(it))
+ FileListerScreen(modifier = Modifier.padding(it), sharedImageUri = if (isUriHandled) null else sharedImageUri, onSharedImageHandled = { isUriHandled = true })
}
}
}
}
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ setIntent(intent)
+ isUriHandled = false
+ handleIntent(intent)
+ }
+
+ private fun handleIntent(intent: Intent?) {
+ if (intent?.action == Intent.ACTION_SEND && intent.type?.startsWith("image/") == true) {
+ sharedImageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
+ }
+ }
}
@Composable
-fun FileListerScreen(modifier: Modifier = Modifier) {
+fun FileListerScreen(modifier: Modifier = Modifier, sharedImageUri: Uri?, onSharedImageHandled: () -> Unit) {
var feedbackText by remember { mutableStateOf("Click a button to see the output here.") }
var picture by remember { mutableStateOf(null) }
val scrollState = rememberScrollState()
@@ -81,10 +102,66 @@ fun FileListerScreen(modifier: Modifier = Modifier) {
.toTypedArray().ifEmpty { null }?.let { askPerm.launch(it) }
}
- Column(
- modifier = modifier.fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally
- ) {
+ val renderAndUpload = { imagePath: String, originalFileName: String ->
+ coroutineScope.launch {
+ try {
+ feedbackText = "Rendering..."
+ val outDir = File("/storage/emulated/0/DCIM/CA_IMAGES_OUT/")
+ val templateStream = context.resources.openRawResource(R.raw.postcard4)
+ val template = BufferedReader(InputStreamReader(templateStream)).readText()
+ val (svg, exif) = genSvg(template, imagePath)
+ val (pic, bytes) = renderSvgBytes(context, svg, exif) ?: return@launch
+ picture = pic
+
+ // Save picture to file
+ outDir.mkdirs()
+ val out = File(outDir, "${File(originalFileName).nameWithoutExtension}-framed.jpg")
+ .apply { writeBytes(bytes) }
+
+ MediaScannerConnection.scanFile(context, arrayOf(out.absolutePath), null, null)
+
+ feedbackText = "Rendered ${originalFileName}, now uploading..."
+
+ val uploadWorkRequest = OneTimeWorkRequestBuilder()
+ .setInputData(workDataOf(
+ "originalPhotoPath" to imagePath,
+ "editedPhotoPath" to out.absolutePath,
+ "urlName" to exif.urlName
+ ))
+ .build()
+ WorkManager.getInstance(context).enqueue(uploadWorkRequest)
+
+ // Launch Canon app
+ context.startActivity(Intent().apply {
+ setClassName("jp.co.canon.ic.photolayout", "jp.co.canon.ic.photolayout.MainActivity")
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ })
+ } catch (e: Exception) {
+ feedbackText = "Error during operation: ${e.message}"
+ Log.e("MainActivity", "Error during render or upload", e)
+ }
+ }
+ }
+
+ LaunchedEffect(sharedImageUri) {
+ if (sharedImageUri == null) return@LaunchedEffect
+
+ feedbackText = "Handling shared image..."
+ val fileName = getFileName(context, sharedImageUri) ?: "shared_image_${System.currentTimeMillis()}.jpg"
+ val tempFile = File(context.cacheDir, fileName)
+ try {
+ context.contentResolver.openInputStream(sharedImageUri)?.use { input ->
+ tempFile.outputStream().use { output -> input.copyTo(output) }
+ }
+ renderAndUpload(tempFile.absolutePath, fileName)
+ onSharedImageHandled()
+ } catch (e: Exception) {
+ feedbackText = "Failed to handle shared image: ${e.message}"
+ Log.e("MainActivity", "Error handling shared image", e)
+ }
+ }
+
+ Column(modifier = modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
Column(modifier = Modifier.weight(1f), horizontalAlignment = Alignment.CenterHorizontally) {
picture?.let { p ->
Canvas(modifier = Modifier.fillMaxWidth().weight(1f).drawWithCache {
@@ -102,61 +179,37 @@ fun FileListerScreen(modifier: Modifier = Modifier) {
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = {
coroutineScope.launch {
- feedbackText = "Rendering..."
val imageDir = File("/storage/emulated/0/DCIM/CA_IMAGES/")
- val outDir = File("/storage/emulated/0/DCIM/CA_IMAGES_OUT/")
val latestImg = imageDir.listFiles()
- ?.filter { !it.name.contains("-framed") and !it.name.contains(".trashed") }
+ ?.filter { !it.name.contains("-framed") && !it.name.contains(".trashed") }
?.maxByOrNull { it.lastModified() }
if (latestImg == null) {
feedbackText = "No images found in CA_IMAGES"
return@launch
}
- try {
- val templateStream = context.resources.openRawResource(R.raw.postcard4)
- val template = BufferedReader(InputStreamReader(templateStream)).readText()
- val (svg, exif) = genSvg(template, latestImg.absolutePath)
- val (pic, bytes) = renderSvgBytes(context, svg, exif) ?: return@launch
- picture = pic
-
- // Save picture to file
- outDir.mkdirs()
- val out = File(outDir, "${latestImg.nameWithoutExtension}-framed.jpg")
- .apply { writeBytes(bytes) }
-
- MediaScannerConnection.scanFile(context, arrayOf(out.absolutePath), null, null)
-
- feedbackText = "Rendered ${latestImg.name}, now uploading..."
-
- val uploadWorkRequest = OneTimeWorkRequestBuilder()
- .setInputData(workDataOf(
- "originalPhotoPath" to latestImg.absolutePath,
- "editedPhotoPath" to out.absolutePath,
- "urlName" to exif.urlName
- ))
- .build()
- WorkManager.getInstance(context).enqueue(uploadWorkRequest)
-
- // Launch Canon app
- context.startActivity(Intent().apply {
- setClassName("jp.co.canon.ic.photolayout", "jp.co.canon.ic.photolayout.MainActivity")
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
- } catch (e: Exception) {
- feedbackText = "Error during operation: ${e.message}"
- Log.e("MainActivity", "Error during render or upload", e)
- }
+ renderAndUpload(latestImg.absolutePath, latestImg.name)
}
}) { Text(text = "Render Latest") }
}
}
}
+private fun getFileName(context: Context, uri: Uri): String? {
+ context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
+ if (cursor.moveToFirst()) {
+ val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
+ if (nameIndex != -1) return cursor.getString(nameIndex)
+ }
+ }
+ return uri.path?.substringAfterLast('/')
+}
+
+
private fun listFilesFromDcim(): String {
val d = File("/storage/emulated/0/DCIM/CA_IMAGES/")
if (!d.exists() || !d.isDirectory) return "Directory not found or is not a directory: ${d.absolutePath}"
- return d.listFiles()?.let {
- it.ifEmpty { null }?.sortedBy { it.lastModified() }?.joinToString("\n") { it.name }
+ return d.listFiles()?.let { files ->
+ files.ifEmpty { null }?.sortedBy { it.lastModified() }?.joinToString("\n") { it.name }
?: "No files found in ${d.absolutePath}"
} ?: "Failed to list files in ${d.absolutePath}. listFiles() returned null."
}
@@ -165,6 +218,6 @@ private fun listFilesFromDcim(): String {
@Composable
fun FileListerScreenPreview() {
ProjectInstantTheme {
- FileListerScreen()
+ FileListerScreen(sharedImageUri = null, onSharedImageHandled = {})
}
}