diff --git a/app/build.gradle b/app/build.gradle index 6db4d849..20fbd587 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,8 +30,8 @@ android { } defaultConfig { minSdkVersion 23 - versionCode 30 targetSdkVersion 34 + versionCode 31 versionName "1.0.beta" + versionCode //TODO add resConfigs("en", "fr", "ja",...) ? diff --git a/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationActivity.kt b/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationActivity.kt index bef490c0..f0f251e1 100644 --- a/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationActivity.kt +++ b/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationActivity.kt @@ -1,5 +1,9 @@ package org.pixeldroid.app.postCreation +import android.content.ClipData +import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Bundle import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment @@ -15,6 +19,31 @@ class PostCreationActivity : BaseActivity() { internal const val POST_REDRAFT = "post_redraft" internal const val POST_NSFW = "post_nsfw" internal const val TEMP_FILES = "temp_files" + + fun intentForUris(context: Context, uris: List) = + Intent(Intent.ACTION_SEND_MULTIPLE).apply { + // Pass downloaded images to new post creation activity + putParcelableArrayListExtra( + Intent.EXTRA_STREAM, ArrayList(uris) + ) + + uris.forEach { + // Why are we using ClipData in addition to parcelableArrayListExtra here? + // Because the FLAG_GRANT_READ_URI_PERMISSION needs to be applied to the URIs, and + // for some reason it doesn't get applied to all of them when not using ClipData + if (clipData == null) { + clipData = ClipData("", emptyArray(), ClipData.Item(it)) + } else { + clipData!!.addItem(ClipData.Item(it)) + } + } + + setClass(context, PostCreationActivity::class.java) + + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) + } + } private lateinit var binding: ActivityPostCreationBinding @@ -32,4 +61,5 @@ class PostCreationActivity : BaseActivity() { } override fun onSupportNavigateUp() = navController.navigateUp() || super.onSupportNavigateUp() + } \ No newline at end of file diff --git a/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationViewModel.kt b/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationViewModel.kt index 08d05f01..40bc5cf9 100644 --- a/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationViewModel.kt +++ b/app/src/main/java/org/pixeldroid/app/postCreation/PostCreationViewModel.kt @@ -1,6 +1,6 @@ package org.pixeldroid.app.postCreation - import android.content.Context +import android.content.Context import android.content.Intent import android.net.Uri import android.os.Parcelable @@ -33,10 +33,10 @@ import kotlinx.parcelize.Parcelize import okhttp3.MultipartBody import org.pixeldroid.app.MainActivity import org.pixeldroid.app.R - import org.pixeldroid.app.postCreation.camera.CameraFragment - import org.pixeldroid.app.utils.api.objects.Attachment - import org.pixeldroid.app.utils.db.AppDatabase - import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity +import org.pixeldroid.app.postCreation.camera.CameraFragment +import org.pixeldroid.app.utils.api.objects.Attachment +import org.pixeldroid.app.utils.db.AppDatabase +import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.fileExtension import org.pixeldroid.app.utils.getMimeType @@ -101,15 +101,31 @@ data class PhotoData( class PostCreationViewModel @Inject constructor( private val state: SavedStateHandle, @ApplicationContext private val applicationContext: Context, - db: AppDatabase + db: AppDatabase, ): ViewModel() { private var storyPhotoDataBackup: MutableList? = null private val photoData: MutableLiveData> by lazy { + //FIXME We should be able to access the Intent action somehow, to determine if there are + // 1 or multiple Uris instead of relying on the ClassCastException + + // This should not work like this (reading its source code, get() function should return null + // if it's the wrong type but instead throws ClassCastException). + // Lucky for us that it does though: we first try to get a single Uri (which we could be + // getting from a share of a single picture to the app), when the cast to Uri fails + // we try to get a list of Uris instead (casting ourselves from Parcelable as suggested + // in get() documentation) + val uris = try { + val singleUri: Uri? = state[Intent.EXTRA_STREAM] + listOfNotNull(singleUri) + } catch (e: ClassCastException) { + state.get>(Intent.EXTRA_STREAM)?.map { it as Uri } + } + MutableLiveData>( addPossibleImages( - state.get>(Intent.EXTRA_STREAM), + uris, state.get>(PostCreationActivity.PICTURE_DESCRIPTIONS), - mutableListOf() + previousList = mutableListOf() ) ) } @@ -160,7 +176,7 @@ class PostCreationViewModel @Inject constructor( * as are legal (if any) and a dialog will be shown to the user alerting them of this fact. */ fun addPossibleImages( - uris: ArrayList?, + uris: List?, descriptions: List?, previousList: MutableList? = photoData.value, ): MutableList { diff --git a/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraActivity.kt b/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraActivity.kt index b007ea5c..af4976b5 100644 --- a/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraActivity.kt +++ b/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraActivity.kt @@ -32,7 +32,7 @@ class CameraActivity : BaseActivity() { // If this CameraActivity wasn't started from the shortcut, // tell the fragment it's in an activity (so that it sends back the result instead of // starting a new post creation process) - if (intent.action != "android.intent.action.VIEW") { + if (intent.action != Intent.ACTION_VIEW) { val arguments = Bundle() arguments.putBoolean(CAMERA_ACTIVITY, true) arguments.putBoolean(CAMERA_ACTIVITY_STORY, story) @@ -47,7 +47,7 @@ class CameraActivity : BaseActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { // If this CameraActivity wasn't started from the shortcut, behave as usual - if (intent.action != "android.intent.action.VIEW") return super.onOptionsItemSelected(item) + if (intent.action != Intent.ACTION_VIEW) return super.onOptionsItemSelected(item) // Else, start a new MainActivity when "going back" on this activity when (item.itemId) { diff --git a/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraFragment.kt b/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraFragment.kt index 76f8d230..a979573b 100644 --- a/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraFragment.kt +++ b/app/src/main/java/org/pixeldroid/app/postCreation/camera/CameraFragment.kt @@ -2,7 +2,6 @@ package org.pixeldroid.app.postCreation.camera import android.Manifest import android.app.Activity -import android.content.ClipData import android.content.ContentUris import android.content.Intent import android.content.pm.PackageManager @@ -38,7 +37,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.pixeldroid.app.databinding.FragmentCameraBinding import org.pixeldroid.app.postCreation.PostCreationActivity -import org.pixeldroid.app.posts.fromHtml import org.pixeldroid.app.utils.BaseFragment import java.io.File import java.util.concurrent.ExecutorService @@ -450,16 +448,7 @@ class CameraFragment : BaseFragment() { private fun startAlbumCreation(uris: ArrayList) { - val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { - // Pass downloaded images to new post creation activity - putParcelableArrayListExtra( - Intent.EXTRA_STREAM, ArrayList(uris.map { it.toUri() }) - ) - setClass(requireContext(), PostCreationActivity::class.java) - - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) - } + val intent = PostCreationActivity.intentForUris(requireContext(), uris.map { it.toUri() }) if(inActivity && !addToStory){ requireActivity().setResult(Activity.RESULT_OK, intent) diff --git a/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt b/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt index d07c0f69..9a7d5b9f 100644 --- a/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt +++ b/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt @@ -536,18 +536,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold ).show() // Create new post creation activity - - //TODO use this instead of clipdata (everywhere) - val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { - // Pass downloaded images to new post creation activity - putParcelableArrayListExtra( - Intent.EXTRA_STREAM, ArrayList(imageUris) - ) - setClass(context, PostCreationActivity::class.java) - - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) - + val intent = PostCreationActivity.intentForUris(context, imageUris).apply { putExtra( PostCreationActivity.PICTURE_DESCRIPTIONS, ArrayList(imageDescriptions) diff --git a/fastlane/metadata/android/en-US/changelogs/31.txt b/fastlane/metadata/android/en-US/changelogs/31.txt new file mode 100644 index 00000000..83ee8f67 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/31.txt @@ -0,0 +1,3 @@ +* Fix crash when sharing an image from gallery etc to the app + +* Fix permission issue causing images to throw a permission denied error