Fix crash when trying to share a text story.

This commit is contained in:
Alex Hart 2022-10-06 09:55:49 -03:00
parent 1fe4c45c44
commit ec46d6039d
2 changed files with 149 additions and 6 deletions

View file

@ -19,9 +19,11 @@ import org.thoughtcrime.securesms.components.menu.ActionItem
import org.thoughtcrime.securesms.components.menu.SignalContextMenu
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
import org.thoughtcrime.securesms.stories.landing.StoriesLandingItem
import org.thoughtcrime.securesms.stories.viewer.page.StoryPost
import org.thoughtcrime.securesms.stories.viewer.page.StoryViewerPageState
import org.thoughtcrime.securesms.util.Base64
import org.thoughtcrime.securesms.util.DeleteDialog
import org.thoughtcrime.securesms.util.SaveAttachmentTask
@ -61,12 +63,23 @@ object StoryContextMenu {
}
fun share(fragment: Fragment, messageRecord: MediaMmsMessageRecord) {
val attachment: Attachment = messageRecord.slideDeck.firstSlide!!.asAttachment()
val intent: Intent = ShareCompat.IntentBuilder(fragment.requireContext())
.setStream(attachment.publicUri)
.setType(attachment.contentType)
.createChooserIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val intent = if (messageRecord.storyType.isTextStory) {
val textStoryBody = StoryTextPost.parseFrom(Base64.decode(messageRecord.body)).body
val linkUrl = messageRecord.linkPreviews.firstOrNull()?.url ?: ""
val shareText = "${textStoryBody} $linkUrl".trim()
ShareCompat.IntentBuilder(fragment.requireContext())
.setText(shareText)
.createChooserIntent()
} else {
val attachment: Attachment = messageRecord.slideDeck.firstSlide!!.asAttachment()
ShareCompat.IntentBuilder(fragment.requireContext())
.setStream(attachment.publicUri)
.setType(attachment.contentType)
.createChooserIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
try {
fragment.startActivity(intent)

View file

@ -0,0 +1,130 @@
package org.thoughtcrime.securesms.stories.dialogs
import android.app.Application
import android.content.Context
import android.content.Intent
import androidx.fragment.app.Fragment
import androidx.test.core.app.ApplicationProvider
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.database.FakeMessageRecords
import org.thoughtcrime.securesms.database.model.StoryType
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
import org.thoughtcrime.securesms.linkpreview.LinkPreview
import org.thoughtcrime.securesms.mms.ImageSlide
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.util.MediaUtil
import org.whispersystems.util.Base64
import java.util.Optional
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class StoryContextMenuTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val intentCaptor = argumentCaptor<Intent>()
private val fragment: Fragment = mock {
on { requireContext() } doReturn context
}
@Test
fun `Given a story with an attachment, when I share, then I expect the correct stream, type, and flag`() {
// GIVEN
val attachmentId = AttachmentId(1, 2)
val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
storyType = StoryType.STORY_WITH_REPLIES,
slideDeck = SlideDeck().apply {
addSlide(
ImageSlide(
context,
FakeMessageRecords.buildDatabaseAttachment(
attachmentId = attachmentId
)
)
)
}
)
// WHEN
StoryContextMenu.share(fragment, storyRecord)
// THEN
verify(fragment).startActivity(intentCaptor.capture())
val chooserIntent: Intent = intentCaptor.firstValue
val targetIntent: Intent = chooserIntent.getParcelableExtra(Intent.EXTRA_INTENT)!!
assertEquals(PartAuthority.getAttachmentPublicUri(PartAuthority.getAttachmentDataUri(attachmentId)), targetIntent.getParcelableExtra(Intent.EXTRA_STREAM))
assertEquals(MediaUtil.IMAGE_JPEG, targetIntent.type)
assertTrue(Intent.FLAG_GRANT_READ_URI_PERMISSION and chooserIntent.flags == Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
@Test
fun `Given a story with a text, when I share, then I expect the correct text`() {
// GIVEN
val expected = "Hello"
val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
storyType = StoryType.TEXT_STORY_WITH_REPLIES,
body = Base64.encodeBytes(StoryTextPost.newBuilder().setBody(expected).build().toByteArray())
)
// WHEN
StoryContextMenu.share(fragment, storyRecord)
// THEN
verify(fragment).startActivity(intentCaptor.capture())
val chooserIntent: Intent = intentCaptor.firstValue
val targetIntent: Intent = chooserIntent.getParcelableExtra(Intent.EXTRA_INTENT)!!
assertEquals(expected, targetIntent.getStringExtra(Intent.EXTRA_TEXT))
}
@Test
fun `Given a story with a link, when I share, then I expect the correct text`() {
// GIVEN
val expected = "https://www.signal.org"
val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
storyType = StoryType.TEXT_STORY_WITH_REPLIES,
body = Base64.encodeBytes(StoryTextPost.newBuilder().build().toByteArray()),
linkPreviews = listOf(LinkPreview(expected, "", "", 0L, Optional.empty()))
)
// WHEN
StoryContextMenu.share(fragment, storyRecord)
// THEN
verify(fragment).startActivity(intentCaptor.capture())
val chooserIntent: Intent = intentCaptor.firstValue
val targetIntent: Intent = chooserIntent.getParcelableExtra(Intent.EXTRA_INTENT)!!
assertEquals(expected, targetIntent.getStringExtra(Intent.EXTRA_TEXT))
}
@Test
fun `Given a story with a text and a link, when I share, then I expect the correct text`() {
// GIVEN
val url = "https://www.signal.org"
val text = "hello"
val expected = "$text $url"
val storyRecord = FakeMessageRecords.buildMediaMmsMessageRecord(
storyType = StoryType.TEXT_STORY_WITH_REPLIES,
body = Base64.encodeBytes(StoryTextPost.newBuilder().setBody(text).build().toByteArray()),
linkPreviews = listOf(LinkPreview(url, "", "", 0L, Optional.empty()))
)
// WHEN
StoryContextMenu.share(fragment, storyRecord)
// THEN
verify(fragment).startActivity(intentCaptor.capture())
val chooserIntent: Intent = intentCaptor.firstValue
val targetIntent: Intent = chooserIntent.getParcelableExtra(Intent.EXTRA_INTENT)!!
assertEquals(expected, targetIntent.getStringExtra(Intent.EXTRA_TEXT))
}
}