Add MediaNoLongerAvailable wiring.

This commit is contained in:
Alex Hart
2024-10-31 15:29:28 -03:00
committed by GitHub
parent 1a8988f825
commit 719ae72270
9 changed files with 167 additions and 0 deletions

View File

@@ -334,5 +334,6 @@ class V2ConversationItemShapeTest {
override fun onItemDoubleClick(item: MultiselectPart) = Unit
override fun onPaymentTombstoneClicked() = Unit
override fun onDisplayMediaNoLongerAvailableSheet() = Unit
}
}

View File

@@ -312,6 +312,10 @@ class InternalConversationTestFragment : Fragment(R.layout.conversation_test_fra
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onDisplayMediaNoLongerAvailableSheet() {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onShowSafetyTips(forGroup: Boolean) {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}

View File

@@ -134,5 +134,6 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
void onMessageRequestAcceptOptionsClicked();
void onItemDoubleClick(MultiselectPart multiselectPart);
void onPaymentTombstoneClicked();
void onDisplayMediaNoLongerAvailableSheet();
}
}

View File

@@ -16,6 +16,8 @@ import org.thoughtcrime.securesms.stickers.StickerLocator
import org.thoughtcrime.securesms.util.ParcelUtil
import org.whispersystems.signalservice.api.util.UuidUtil
import java.util.UUID
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
/**
* Note: We have to use our own Parcelable implementation because we need to do custom stuff to preserve
@@ -146,6 +148,12 @@ abstract class Attachment(
val isPermanentlyFailed: Boolean
get() = transferState == AttachmentTable.TRANSFER_PROGRESS_PERMANENT_FAILURE
/**
* Denotes whether the media for the given attachment is no longer available for download.
*/
val isMediaNoLongerAvailableForDownload: Boolean
get() = isPermanentlyFailed && uploadTimestamp.milliseconds > 30.days
val isSticker: Boolean
get() = stickerLocator != null

View File

@@ -80,6 +80,7 @@ import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.badges.BadgeImageView;
import org.thoughtcrime.securesms.badges.gifts.GiftMessageView;
import org.thoughtcrime.securesms.badges.gifts.OpenableGift;
import org.thoughtcrime.securesms.billing.upgrade.UpgradeToStartMediaBackupSheet;
import org.thoughtcrime.securesms.calls.links.CallLinks;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AudioView;
@@ -2607,6 +2608,11 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
Log.w(TAG, "No activity existed to view the media.");
Toast.makeText(context, R.string.ConversationItem_unable_to_open_media, Toast.LENGTH_LONG).show();
}
} else if (slide.asAttachment().isMediaNoLongerAvailableForDownload() && !SignalStore.backup().backsUpMedia()) {
Log.i(TAG, "Clicked unavailable media, attempting to display sheet.");
if (eventListener != null) {
eventListener.onDisplayMediaNoLongerAvailableSheet();
}
} else if (slide.asAttachment().isPermanentlyFailed()) {
String failedMessage;

View File

@@ -112,6 +112,7 @@ import org.thoughtcrime.securesms.badges.gifts.OpenableGift
import org.thoughtcrime.securesms.badges.gifts.OpenableGiftItemDecoration
import org.thoughtcrime.securesms.badges.gifts.viewgift.received.ViewReceivedGiftBottomSheet
import org.thoughtcrime.securesms.badges.gifts.viewgift.sent.ViewSentGiftBottomSheet
import org.thoughtcrime.securesms.billing.upgrade.UpgradeToStartMediaBackupSheet
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar
import org.thoughtcrime.securesms.components.AnimatingToggle
import org.thoughtcrime.securesms.components.ComposeText
@@ -2895,6 +2896,14 @@ class ConversationFragment :
this@ConversationFragment.showPaymentTombstoneLearnMoreDialog()
}
override fun onDisplayMediaNoLongerAvailableSheet() {
if (SignalStore.backup.areBackupsEnabled) {
UpgradeToStartMediaBackupSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
} else {
MediaNoLongerAvailableBottomSheet().show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
}
override fun onMessageWithErrorClicked(messageRecord: MessageRecord) {
val recipientId = viewModel.recipientSnapshot?.id ?: return
if (messageRecord.isIdentityMismatchFailure) {

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.conversation.v2
import android.os.Bundle
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.signal.core.ui.BottomSheets
import org.signal.core.ui.Buttons
import org.signal.core.ui.Previews
import org.signal.core.ui.SignalPreview
import org.signal.core.ui.horizontalGutters
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
import org.thoughtcrime.securesms.components.settings.app.subscription.MessageBackupsCheckoutLauncher.createBackupsCheckoutLauncher
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
/**
* Bottom sheet displayed when the user taps media that is not available for download,
* over 30 days old, and they do not currently have a subscription.
*/
class MediaNoLongerAvailableBottomSheet : ComposeBottomSheetDialogFragment() {
private lateinit var checkoutLauncher: ActivityResultLauncher<MessageBackupTier?>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
checkoutLauncher = createBackupsCheckoutLauncher {
dismissAllowingStateLoss()
}
}
@Composable
override fun SheetContent() {
MediaNoLongerAvailableBottomSheetContent(
onContinueClick = {
checkoutLauncher.launch(MessageBackupTier.PAID)
},
onNotNowClick = { dismissAllowingStateLoss() }
)
}
}
@Composable
private fun MediaNoLongerAvailableBottomSheetContent(
onContinueClick: () -> Unit = {},
onNotNowClick: () -> Unit = {}
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.horizontalGutters()
) {
BottomSheets.Handle()
Image(
painter = painterResource(R.drawable.image_signal_backups_media),
contentDescription = null,
modifier = Modifier.padding(vertical = 16.dp)
)
Text(
text = stringResource(R.string.MediaNoLongerAvailableSheet__this_media_is_no_longer_available),
style = MaterialTheme.typography.titleLarge,
textAlign = TextAlign.Center,
modifier = Modifier.padding(bottom = 10.dp)
)
Text(
text = stringResource(R.string.MediaNoLongerAvailableSheet__to_start_backing_up_all_your_media),
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = Modifier.padding(bottom = 92.dp)
)
Buttons.LargeTonal(
onClick = onContinueClick,
modifier = Modifier
.padding(bottom = 22.dp)
.defaultMinSize(minWidth = 220.dp)
) {
Text(
text = stringResource(R.string.MediaNoLongerAvailableSheet__continue)
)
}
TextButton(
onClick = onNotNowClick,
modifier = Modifier
.padding(bottom = 32.dp)
.defaultMinSize(minWidth = 220.dp)
) {
Text(
text = stringResource(R.string.MediaNoLongerAvailableSheet__not_now)
)
}
}
}
@SignalPreview
@Composable
private fun MediaNoLongerAvailableBottomSheetContentPreview() {
Previews.BottomSheetPreview {
MediaNoLongerAvailableBottomSheetContent()
}
}

View File

@@ -382,6 +382,10 @@ class MessageDetailsFragment : FullScreenDialogFragment(), MessageDetailsAdapter
Log.w(TAG, "Not yet implemented!", Exception())
}
override fun onDisplayMediaNoLongerAvailableSheet() {
Log.w(TAG, "Not yet implemented!", Exception())
}
interface Callback {
fun onMessageDetailsFragmentDismissed()
}

View File

@@ -7565,6 +7565,16 @@
<!-- Primary action to launch upgrade flow. Placeholder is formatted price. -->
<string name="UpgradeToStartMediaBackupSheet__subscribe_for_s_month">Subscribe for %1$s/month</string>
<!-- MediaNoLongerAvailableSheet -->
<!-- Title on a bottom sheet explaining that the given media is no longer available. -->
<string name="MediaNoLongerAvailableSheet__this_media_is_no_longer_available">This media is no longer available</string>
<!-- Body on a bottom sheet explaining that the user can enable backups -->
<string name="MediaNoLongerAvailableSheet__to_start_backing_up_all_your_media">To start backing up all your media, enable Signal Backups and choose the paid tier.</string>
<!-- Primary action button on bottom sheet -->
<string name="MediaNoLongerAvailableSheet__continue">Continue</string>
<!-- Secondary action button on bottom sheet -->
<string name="MediaNoLongerAvailableSheet__not_now">Not now</string>
<!-- Educational bottom sheet dialog title shown to notify about delete syncs causing deletes to happen across all devices -->
<string name="DeleteSyncEducation_title">Deleting is now synced across all of your devices</string>
<!-- Educational bottom sheet dialog message shown to notify about delete syncs causing deletes to happen across all devices -->