mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 12:44:38 +00:00
Allow canceling media attachment send.
This commit is contained in:
committed by
Alex Hart
parent
deacf28d77
commit
5022d81d9a
@@ -30,9 +30,9 @@ import java.util.List;
|
||||
public class AlbumThumbnailView extends FrameLayout {
|
||||
|
||||
private @Nullable SlideClickListener thumbnailClickListener;
|
||||
private @Nullable SlidesClickedListener downloadClickListener;
|
||||
private @Nullable SlidesClickedListener cancelDownloadClickListener;
|
||||
private @Nullable SlideClickListener playVideoClickListener;
|
||||
private @Nullable SlidesClickedListener startTransferClickListener;
|
||||
private @Nullable SlidesClickedListener cancelTransferClickListener;
|
||||
private @Nullable SlideClickListener playVideoClickListener;
|
||||
|
||||
private int currentSizeClass;
|
||||
|
||||
@@ -72,16 +72,16 @@ public class AlbumThumbnailView extends FrameLayout {
|
||||
|
||||
if (showControls) {
|
||||
transferControlsStub.get().setShowSecondaryText(true);
|
||||
transferControlsStub.get().setDownloadClickListener(
|
||||
transferControlsStub.get().setTransferClickListener(
|
||||
v -> {
|
||||
if (downloadClickListener != null) {
|
||||
downloadClickListener.onClick(v, slides);
|
||||
if (startTransferClickListener != null) {
|
||||
startTransferClickListener.onClick(v, slides);
|
||||
}
|
||||
});
|
||||
transferControlsStub.get().setCancelClickListener(
|
||||
v -> {
|
||||
if (cancelDownloadClickListener != null) {
|
||||
cancelDownloadClickListener.onClick(v, slides);
|
||||
if (cancelTransferClickListener != null) {
|
||||
cancelTransferClickListener.onClick(v, slides);
|
||||
}
|
||||
});
|
||||
transferControlsStub.get().setSlides(slides);
|
||||
@@ -117,12 +117,12 @@ public class AlbumThumbnailView extends FrameLayout {
|
||||
thumbnailClickListener = listener;
|
||||
}
|
||||
|
||||
public void setDownloadClickListener(SlidesClickedListener listener) {
|
||||
this.downloadClickListener = listener;
|
||||
public void setStartTransferClickListener(SlidesClickedListener listener) {
|
||||
this.startTransferClickListener = listener;
|
||||
}
|
||||
|
||||
public void setCancelDownloadClickListener(SlidesClickedListener listener) {
|
||||
this.cancelDownloadClickListener = listener;
|
||||
public void setCancelTransferClickListener(SlidesClickedListener listener) {
|
||||
this.cancelTransferClickListener = listener;
|
||||
}
|
||||
|
||||
public void setPlayVideoClickListener(SlideClickListener listener) {
|
||||
@@ -288,8 +288,8 @@ public class AlbumThumbnailView extends FrameLayout {
|
||||
ThumbnailView cell = findViewById(id);
|
||||
cell.showSecondaryText(false);
|
||||
cell.setThumbnailClickListener(defaultThumbnailClickListener);
|
||||
cell.setDownloadClickListener(downloadClickListener);
|
||||
cell.setCancelDownloadClickListener(cancelDownloadClickListener);
|
||||
cell.setStartTransferClickListener(startTransferClickListener);
|
||||
cell.setCancelTransferClickListener(cancelTransferClickListener);
|
||||
if (MediaUtil.isInstantVideoSupported(slide)) {
|
||||
cell.setPlayVideoClickListener(playVideoClickListener);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ import android.widget.ImageView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterInside;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
@@ -74,6 +71,6 @@ public class BorderlessImageView extends FrameLayout {
|
||||
}
|
||||
|
||||
public void setDownloadClickListener(@NonNull SlidesClickedListener listener) {
|
||||
image.setDownloadClickListener(listener);
|
||||
image.setStartTransferClickListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode;
|
||||
import org.thoughtcrime.securesms.conversation.v2.computed.FormattedDate;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -302,7 +302,9 @@ public class ConversationItemFooter extends ConstraintLayout {
|
||||
|
||||
private void presentDate(@NonNull MessageRecord messageRecord, @NonNull Locale locale, @NonNull ConversationItemDisplayMode displayMode) {
|
||||
dateView.forceLayout();
|
||||
if (messageRecord.isFailed()) {
|
||||
if (messageRecord.isMediaPending()) {
|
||||
dateView.setText(null);
|
||||
} else if (messageRecord.isFailed()) {
|
||||
int errorMsg;
|
||||
if (messageRecord.hasFailedWithNetworkFailures()) {
|
||||
errorMsg = R.string.ConversationItem_error_network_not_delivered;
|
||||
|
||||
@@ -251,10 +251,10 @@ class ConversationItemThumbnail @JvmOverloads constructor(
|
||||
state.applyState(thumbnail, album)
|
||||
}
|
||||
|
||||
fun setDownloadClickListener(listener: SlidesClickedListener?) {
|
||||
fun setStartTransferClickListener(listener: SlidesClickedListener?) {
|
||||
state = state.copy(
|
||||
thumbnailViewState = state.thumbnailViewState.copy(downloadClickListener = listener),
|
||||
albumViewState = state.albumViewState.copy(downloadClickListener = listener)
|
||||
thumbnailViewState = state.thumbnailViewState.copy(startTransferClickListener = listener),
|
||||
albumViewState = state.albumViewState.copy(startTransferClickListener = listener)
|
||||
)
|
||||
|
||||
state.applyState(thumbnail, album)
|
||||
@@ -269,10 +269,10 @@ class ConversationItemThumbnail @JvmOverloads constructor(
|
||||
state.applyState(thumbnail, album)
|
||||
}
|
||||
|
||||
fun setCancelDownloadClickListener(listener: SlidesClickedListener?) {
|
||||
fun setCancelTransferClickListener(listener: SlidesClickedListener?) {
|
||||
state = state.copy(
|
||||
thumbnailViewState = state.thumbnailViewState.copy(cancelDownloadClickListener = listener),
|
||||
albumViewState = state.albumViewState.copy(cancelDownloadClickListener = listener)
|
||||
thumbnailViewState = state.thumbnailViewState.copy(cancelTransferClickListener = listener),
|
||||
albumViewState = state.albumViewState.copy(cancelTransferClickListener = listener)
|
||||
)
|
||||
|
||||
state.applyState(thumbnail, album)
|
||||
|
||||
@@ -34,9 +34,9 @@ data class ConversationItemThumbnailState(
|
||||
@IgnoredOnParcel
|
||||
private val clickListener: SlideClickListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val downloadClickListener: SlidesClickedListener? = null,
|
||||
private val startTransferClickListener: SlidesClickedListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val cancelDownloadClickListener: SlidesClickedListener? = null,
|
||||
private val cancelTransferClickListener: SlidesClickedListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val playVideoClickListener: SlideClickListener? = null,
|
||||
@IgnoredOnParcel
|
||||
@@ -63,8 +63,8 @@ data class ConversationItemThumbnailState(
|
||||
thumbnailView.get().isClickable = clickable
|
||||
thumbnailView.get().setRadii(cornerTopLeft, cornerTopRight, cornerBottomRight, cornerBottomLeft)
|
||||
thumbnailView.get().setThumbnailClickListener(clickListener)
|
||||
thumbnailView.get().setDownloadClickListener(downloadClickListener)
|
||||
thumbnailView.get().setCancelDownloadClickListener(cancelDownloadClickListener)
|
||||
thumbnailView.get().setStartTransferClickListener(startTransferClickListener)
|
||||
thumbnailView.get().setCancelTransferClickListener(cancelTransferClickListener)
|
||||
thumbnailView.get().setPlayVideoClickListener(playVideoClickListener)
|
||||
thumbnailView.get().setOnLongClickListener(longClickListener)
|
||||
thumbnailView.get().setBounds(minWidth, maxWidth, minHeight, maxHeight)
|
||||
@@ -78,9 +78,9 @@ data class ConversationItemThumbnailState(
|
||||
@IgnoredOnParcel
|
||||
private val clickListener: SlideClickListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val downloadClickListener: SlidesClickedListener? = null,
|
||||
private val startTransferClickListener: SlidesClickedListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val cancelDownloadClickListener: SlidesClickedListener? = null,
|
||||
private val cancelTransferClickListener: SlidesClickedListener? = null,
|
||||
@IgnoredOnParcel
|
||||
private val playVideoClickListener: SlideClickListener? = null,
|
||||
@IgnoredOnParcel
|
||||
@@ -103,8 +103,8 @@ data class ConversationItemThumbnailState(
|
||||
albumView.get().isClickable = clickable
|
||||
albumView.get().setRadii(cornerTopLeft, cornerTopRight, cornerBottomRight, cornerBottomLeft)
|
||||
albumView.get().setThumbnailClickListener(clickListener)
|
||||
albumView.get().setDownloadClickListener(downloadClickListener)
|
||||
albumView.get().setCancelDownloadClickListener(cancelDownloadClickListener)
|
||||
albumView.get().setStartTransferClickListener(startTransferClickListener)
|
||||
albumView.get().setCancelTransferClickListener(cancelTransferClickListener)
|
||||
albumView.get().setPlayVideoClickListener(playVideoClickListener)
|
||||
albumView.get().setOnLongClickListener(longClickListener)
|
||||
albumView.get().setCellBackgroundColor(cellBackgroundColor)
|
||||
|
||||
@@ -22,7 +22,7 @@ data class LinkPreviewViewThumbnailState(
|
||||
fun applyState(thumbnail: Stub<OutlinedThumbnailView>) {
|
||||
if (thumbnail.resolved()) {
|
||||
thumbnail.get().setCorners(cornerTopLeft, cornerTopRight, cornerBottomRight, cornerBottomLeft)
|
||||
thumbnail.get().setDownloadClickListener(downloadListener)
|
||||
thumbnail.get().setStartTransferClickListener(downloadListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,12 +86,12 @@ public class ThumbnailView extends FrameLayout {
|
||||
|
||||
private final CornerMask cornerMask;
|
||||
|
||||
private final Stub<TransferControlView> transferControlViewStub;
|
||||
private SlideClickListener thumbnailClickListener = null;
|
||||
private SlidesClickedListener downloadClickListener = null;
|
||||
private SlidesClickedListener cancelDownloadClickListener = null;
|
||||
private SlideClickListener playVideoClickListener = null;
|
||||
private Slide slide = null;
|
||||
private final Stub<TransferControlView> transferControlViewStub;
|
||||
private SlideClickListener thumbnailClickListener = null;
|
||||
private SlidesClickedListener startTransferClickListener = null;
|
||||
private SlidesClickedListener cancelTransferClickListener = null;
|
||||
private SlideClickListener playVideoClickListener = null;
|
||||
private Slide slide = null;
|
||||
|
||||
|
||||
public ThumbnailView(Context context) {
|
||||
@@ -363,7 +363,7 @@ public class ThumbnailView extends FrameLayout {
|
||||
}
|
||||
|
||||
if (showControls) {
|
||||
transferControlViewStub.get().setDownloadClickListener(new DownloadClickDispatcher());
|
||||
transferControlViewStub.get().setTransferClickListener(new DownloadClickDispatcher());
|
||||
transferControlViewStub.get().setCancelClickListener(new CancelClickDispatcher());
|
||||
if (MediaUtil.isInstantVideoSupported(slide)) {
|
||||
transferControlViewStub.get().setInstantPlaybackClickListener(new InstantVideoClickDispatcher());
|
||||
@@ -516,12 +516,12 @@ public class ThumbnailView extends FrameLayout {
|
||||
this.thumbnailClickListener = listener;
|
||||
}
|
||||
|
||||
public void setDownloadClickListener(SlidesClickedListener listener) {
|
||||
this.downloadClickListener = listener;
|
||||
public void setStartTransferClickListener(SlidesClickedListener listener) {
|
||||
this.startTransferClickListener = listener;
|
||||
}
|
||||
|
||||
public void setCancelDownloadClickListener(SlidesClickedListener listener) {
|
||||
this.cancelDownloadClickListener = listener;
|
||||
public void setCancelTransferClickListener(SlidesClickedListener listener) {
|
||||
this.cancelTransferClickListener = listener;
|
||||
}
|
||||
|
||||
public void setPlayVideoClickListener(SlideClickListener listener) {
|
||||
@@ -667,10 +667,10 @@ public class ThumbnailView extends FrameLayout {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.i(TAG, "onClick() for download button");
|
||||
if (downloadClickListener != null && slide != null) {
|
||||
downloadClickListener.onClick(view, Collections.singletonList(slide));
|
||||
if (startTransferClickListener != null && slide != null) {
|
||||
startTransferClickListener.onClick(view, Collections.singletonList(slide));
|
||||
} else {
|
||||
Log.w(TAG, "Received a download button click, but unable to execute it. slide: " + slide + " downloadClickListener: " + downloadClickListener);
|
||||
Log.w(TAG, "Received a download button click, but unable to execute it. slide: " + slide + " downloadClickListener: " + startTransferClickListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -679,10 +679,10 @@ public class ThumbnailView extends FrameLayout {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Log.i(TAG, "onClick() for cancel button");
|
||||
if (cancelDownloadClickListener != null && slide != null) {
|
||||
cancelDownloadClickListener.onClick(view, Collections.singletonList(slide));
|
||||
if (cancelTransferClickListener != null && slide != null) {
|
||||
cancelTransferClickListener.onClick(view, Collections.singletonList(slide));
|
||||
} else {
|
||||
Log.w(TAG, "Received a cancel button click, but unable to execute it. slide: " + slide + " cancelDownloadClickListener: " + cancelDownloadClickListener);
|
||||
Log.w(TAG, "Received a cancel button click, but unable to execute it. slide: " + slide + " cancelDownloadClickListener: " + cancelTransferClickListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
|
||||
private fun displayPendingGallery(currentState: TransferControlViewState) {
|
||||
binding.primaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.primaryProgressView.startClickListener = currentState.startTransferClickListener
|
||||
applyFocusableAndClickable(
|
||||
currentState,
|
||||
listOf(binding.primaryProgressView, binding.primaryDetailsText, binding.primaryBackground),
|
||||
@@ -228,8 +228,8 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
secondaryDetailsText = currentState.showSecondaryText
|
||||
)
|
||||
|
||||
binding.primaryDetailsText.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.primaryBackground.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.primaryDetailsText.setOnClickListener(currentState.startTransferClickListener)
|
||||
binding.primaryBackground.setOnClickListener(currentState.startTransferClickListener)
|
||||
|
||||
binding.primaryDetailsText.translationX = if (ViewUtil.isLtr(this)) {
|
||||
ViewUtil.dpToPx(-PRIMARY_TEXT_OFFSET_DP).toFloat()
|
||||
@@ -244,7 +244,7 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
|
||||
private fun displayPendingGalleryWithPlayable(currentState: TransferControlViewState) {
|
||||
binding.secondaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.secondaryProgressView.startClickListener = currentState.startTransferClickListener
|
||||
super.setClickable(false)
|
||||
binding.secondaryProgressView.isClickable = currentState.showSecondaryText
|
||||
binding.secondaryProgressView.isFocusable = currentState.showSecondaryText
|
||||
@@ -269,7 +269,7 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
|
||||
private fun displayPendingSingleItem(currentState: TransferControlViewState) {
|
||||
binding.primaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.primaryProgressView.startClickListener = currentState.startTransferClickListener
|
||||
applyFocusableAndClickable(currentState, listOf(binding.primaryProgressView), listOf(binding.secondaryProgressView, binding.playVideoButton))
|
||||
binding.primaryProgressView.setStopped(false)
|
||||
showAllViews(
|
||||
@@ -284,9 +284,9 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
|
||||
private fun displayPendingPlayableVideo(currentState: TransferControlViewState) {
|
||||
binding.secondaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.secondaryDetailsText.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.secondaryBackground.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.secondaryProgressView.startClickListener = currentState.startTransferClickListener
|
||||
binding.secondaryDetailsText.setOnClickListener(currentState.startTransferClickListener)
|
||||
binding.secondaryBackground.setOnClickListener(currentState.startTransferClickListener)
|
||||
binding.playVideoButton.setOnClickListener(currentState.instantPlaybackClickListener)
|
||||
applyFocusableAndClickable(
|
||||
currentState,
|
||||
@@ -320,17 +320,17 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
|
||||
val progress = calculateProgress(currentState)
|
||||
if (progress == 0f) {
|
||||
binding.secondaryProgressView.setUploading(progress)
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
} else {
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelDownloadClickedListener
|
||||
binding.secondaryProgressView.setDownloading(progress)
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelTransferClickedListener
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
}
|
||||
binding.secondaryDetailsText.translationX = 0f
|
||||
binding.secondaryDetailsText.text = deriveSecondaryDetailsText(currentState)
|
||||
}
|
||||
|
||||
private fun displayDownloadingSingleItem(currentState: TransferControlViewState) {
|
||||
binding.primaryProgressView.cancelClickListener = currentState.cancelDownloadClickedListener
|
||||
binding.primaryProgressView.cancelClickListener = currentState.cancelTransferClickedListener
|
||||
applyFocusableAndClickable(currentState, listOf(binding.primaryProgressView), listOf(binding.secondaryProgressView, binding.playVideoButton))
|
||||
showAllViews(
|
||||
playVideoButton = false,
|
||||
@@ -341,16 +341,16 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
|
||||
val progress = calculateProgress(currentState)
|
||||
if (progress == 0f) {
|
||||
binding.primaryProgressView.setUploading(progress)
|
||||
binding.primaryProgressView.setProgress(progress)
|
||||
} else {
|
||||
binding.primaryProgressView.setDownloading(progress)
|
||||
binding.primaryProgressView.setProgress(progress)
|
||||
}
|
||||
binding.secondaryDetailsText.translationX = 0f
|
||||
binding.secondaryDetailsText.text = deriveSecondaryDetailsText(currentState)
|
||||
}
|
||||
|
||||
private fun displayDownloadingPlayableVideo(currentState: TransferControlViewState) {
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelDownloadClickedListener
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelTransferClickedListener
|
||||
applyFocusableAndClickable(currentState, listOf(binding.secondaryProgressView, binding.playVideoButton), listOf(binding.primaryProgressView))
|
||||
showAllViews(
|
||||
primaryDetailsText = false,
|
||||
@@ -362,16 +362,16 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
|
||||
val progress = calculateProgress(currentState)
|
||||
if (progress == 0f) {
|
||||
binding.secondaryProgressView.setUploading(progress)
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
} else {
|
||||
binding.secondaryProgressView.setDownloading(progress)
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
}
|
||||
binding.secondaryDetailsText.translationX = 0f
|
||||
binding.secondaryDetailsText.text = deriveSecondaryDetailsText(currentState)
|
||||
}
|
||||
|
||||
private fun displayUploadingSingleItem(currentState: TransferControlViewState) {
|
||||
binding.secondaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelTransferClickedListener
|
||||
applyFocusableAndClickable(currentState, listOf(binding.secondaryProgressView), listOf(binding.primaryProgressView, binding.playVideoButton))
|
||||
showAllViews(
|
||||
playVideoButton = false,
|
||||
@@ -381,18 +381,14 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
)
|
||||
|
||||
val progress = calculateProgress(currentState)
|
||||
binding.secondaryProgressView.setUploading(progress)
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
|
||||
binding.secondaryDetailsText.translationX = 0f
|
||||
binding.secondaryDetailsText.text = deriveSecondaryDetailsText(currentState)
|
||||
}
|
||||
|
||||
private fun displayUploadingGallery(currentState: TransferControlViewState) {
|
||||
if (currentState.downloadClickedListener == null) {
|
||||
Log.w(TAG, "No click listener set for retry!")
|
||||
}
|
||||
|
||||
binding.secondaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.secondaryProgressView.cancelClickListener = currentState.cancelTransferClickedListener
|
||||
applyFocusableAndClickable(currentState, listOf(binding.secondaryProgressView), listOf(binding.primaryProgressView, binding.playVideoButton))
|
||||
showAllViews(
|
||||
playVideoButton = false,
|
||||
@@ -401,18 +397,18 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
)
|
||||
|
||||
val progress = calculateProgress(currentState)
|
||||
binding.secondaryProgressView.setUploading(progress)
|
||||
binding.secondaryProgressView.setProgress(progress)
|
||||
|
||||
binding.secondaryDetailsText.translationX = 0f
|
||||
binding.secondaryDetailsText.text = deriveSecondaryDetailsText(currentState)
|
||||
}
|
||||
|
||||
private fun displayRetry(currentState: TransferControlViewState, isUploading: Boolean) {
|
||||
if (currentState.downloadClickedListener == null) {
|
||||
if (currentState.startTransferClickListener == null) {
|
||||
Log.w(TAG, "No click listener set for retry!")
|
||||
}
|
||||
|
||||
binding.secondaryProgressView.startClickListener = currentState.downloadClickedListener
|
||||
binding.secondaryProgressView.startClickListener = currentState.startTransferClickListener
|
||||
applyFocusableAndClickable(
|
||||
currentState,
|
||||
listOf(binding.secondaryProgressView, binding.secondaryDetailsText, binding.secondaryBackground),
|
||||
@@ -429,8 +425,8 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
} else {
|
||||
ViewUtil.dpToPx(RETRY_SECONDARY_TEXT_OFFSET_DP).toFloat()
|
||||
}
|
||||
binding.secondaryBackground.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.secondaryDetailsText.setOnClickListener(currentState.downloadClickedListener)
|
||||
binding.secondaryBackground.setOnClickListener(currentState.startTransferClickListener)
|
||||
binding.secondaryDetailsText.setOnClickListener(currentState.startTransferClickListener)
|
||||
binding.secondaryProgressView.setStopped(isUploading)
|
||||
binding.secondaryDetailsText.text = resources.getString(R.string.NetworkFailure__retry)
|
||||
}
|
||||
@@ -594,11 +590,11 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
return true
|
||||
}
|
||||
|
||||
fun setDownloadClickListener(listener: OnClickListener) {
|
||||
verboseLog("downloadClickListener update")
|
||||
fun setTransferClickListener(listener: OnClickListener) {
|
||||
verboseLog("transferClickListener update")
|
||||
updateState {
|
||||
it.copy(
|
||||
downloadClickedListener = listener
|
||||
startTransferClickListener = listener
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -607,7 +603,7 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
verboseLog("cancelClickListener update")
|
||||
updateState {
|
||||
it.copy(
|
||||
cancelDownloadClickedListener = listener
|
||||
cancelTransferClickedListener = listener
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -660,7 +656,7 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun deriveSecondaryDetailsText(currentState: TransferControlViewState): String {
|
||||
return if (isCompressing(currentState)) {
|
||||
return if (currentState.networkProgress.sumCompleted() == 0L || isCompressing(currentState)) {
|
||||
return context.getString(R.string.TransferControlView__processing)
|
||||
} else {
|
||||
val progressMiB = currentState.networkProgress.sumCompleted() / MEBIBYTE
|
||||
|
||||
@@ -14,8 +14,8 @@ data class TransferControlViewState(
|
||||
val isFocusable: Boolean = true,
|
||||
val isClickable: Boolean = true,
|
||||
val slides: List<Slide> = emptyList(),
|
||||
val downloadClickedListener: View.OnClickListener? = null,
|
||||
val cancelDownloadClickedListener: View.OnClickListener? = null,
|
||||
val startTransferClickListener: View.OnClickListener? = null,
|
||||
val cancelTransferClickedListener: View.OnClickListener? = null,
|
||||
val instantPlaybackClickListener: View.OnClickListener? = null,
|
||||
val showSecondaryText: Boolean = true,
|
||||
val networkProgress: Map<Attachment, TransferControlView.Progress> = HashMap(),
|
||||
|
||||
@@ -97,7 +97,7 @@ class TransferProgressView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun setDownloading(progress: Float) {
|
||||
fun setProgress(progress: Float) {
|
||||
currentState = State.IN_PROGRESS_CANCELABLE
|
||||
if (cancelClickListener == null) {
|
||||
Log.i(TAG, "Illegal click listener attached.")
|
||||
@@ -108,13 +108,6 @@ class TransferProgressView @JvmOverloads constructor(
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setUploading(progress: Float) {
|
||||
currentState = State.IN_PROGRESS_NON_CANCELABLE
|
||||
setOnClickListener { Log.d(TAG, "Not allowed to click an upload.") }
|
||||
progressPercent = progress
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setStopped(isUpload: Boolean) {
|
||||
val newState = if (isUpload) State.READY_TO_UPLOAD else State.READY_TO_DOWNLOAD
|
||||
currentState = newState
|
||||
|
||||
@@ -95,6 +95,8 @@ import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
|
||||
import org.thoughtcrime.securesms.contactshare.Contact;
|
||||
import org.thoughtcrime.securesms.conversation.clicklisteners.AttachmentCancelClickListener;
|
||||
import org.thoughtcrime.securesms.conversation.clicklisteners.ResendClickListener;
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectCollection;
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart;
|
||||
@@ -1083,7 +1085,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
boolean messageRequestAccepted,
|
||||
boolean allowedToPlayInline)
|
||||
{
|
||||
boolean showControls = !messageRecord.isFailed() && !MessageRecordUtil.isScheduled(messageRecord);
|
||||
boolean showControls = messageRecord.isMediaPending() || (!messageRecord.isFailed() && !MessageRecordUtil.isScheduled(messageRecord));
|
||||
|
||||
ViewUtil.setTopMargin(bodyText, readDimen(R.dimen.message_bubble_top_padding));
|
||||
|
||||
@@ -1174,8 +1176,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
mediaThumbnailStub.require().setMaximumThumbnailHeight(readDimen(R.dimen.media_bubble_max_height));
|
||||
mediaThumbnailStub.require().setImageResource(glideRequests, Collections.singletonList(new ImageSlide(linkPreview.getThumbnail().get())), showControls, false);
|
||||
mediaThumbnailStub.require().setThumbnailClickListener(new LinkPreviewThumbnailClickListener());
|
||||
mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener);
|
||||
mediaThumbnailStub.require().setCancelDownloadClickListener(attachmentCancelClickListener);
|
||||
mediaThumbnailStub.require().setStartTransferClickListener(downloadClickListener);
|
||||
mediaThumbnailStub.require().setCancelTransferClickListener(attachmentCancelClickListener);
|
||||
mediaThumbnailStub.require().setPlayVideoClickListener(playVideoClickListener);
|
||||
mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener);
|
||||
|
||||
@@ -1312,8 +1314,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
: R.dimen.media_bubble_max_height));
|
||||
|
||||
mediaThumbnailStub.require().setThumbnailClickListener(new ThumbnailClickListener());
|
||||
mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener);
|
||||
mediaThumbnailStub.require().setCancelDownloadClickListener(attachmentCancelClickListener);
|
||||
mediaThumbnailStub.require().setCancelTransferClickListener(attachmentCancelClickListener);
|
||||
mediaThumbnailStub.require().setPlayVideoClickListener(playVideoClickListener);
|
||||
mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.require().setOnClickListener(passthroughClickListener);
|
||||
@@ -1324,8 +1325,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
false);
|
||||
if (!messageRecord.isOutgoing()) {
|
||||
mediaThumbnailStub.require().setConversationColor(getDefaultBubbleColor(hasWallpaper));
|
||||
mediaThumbnailStub.require().setStartTransferClickListener(downloadClickListener);
|
||||
} else {
|
||||
mediaThumbnailStub.require().setConversationColor(Color.TRANSPARENT);
|
||||
mediaThumbnailStub.require().setStartTransferClickListener(new ResendClickListener(messageRecord));
|
||||
}
|
||||
|
||||
mediaThumbnailStub.require().setBorderless(false);
|
||||
@@ -1566,7 +1569,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
private void setStatusIcons(MessageRecord messageRecord, boolean hasWallpaper) {
|
||||
bodyText.setCompoundDrawablesWithIntrinsicBounds(0, 0, messageRecord.isKeyExchange() ? R.drawable.ic_menu_login : 0, 0);
|
||||
|
||||
if (messageRecord.isFailed()) {
|
||||
if (!messageRecord.isMediaPending() && messageRecord.isFailed()) {
|
||||
alertView.setFailed();
|
||||
} else if (messageRecord.isPendingInsecureSmsFallback()) {
|
||||
alertView.setPendingApproval();
|
||||
@@ -2445,25 +2448,6 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
}
|
||||
}
|
||||
|
||||
private class AttachmentCancelClickListener implements SlidesClickedListener {
|
||||
@Override
|
||||
public void onClick(View v, List<Slide> slides) {
|
||||
Log.i(TAG, "onClick() for attachment cancellation");
|
||||
final JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||
if (messageRecord.isMmsNotification()) {
|
||||
Log.i(TAG, "Canceling MMS attachments download");
|
||||
jobManager.cancel("mms-operation");
|
||||
} else {
|
||||
Log.i(TAG, "Canceling push attachment downloads for " + slides.size() + " items");
|
||||
|
||||
for (Slide slide : slides) {
|
||||
final String queue = AttachmentDownloadJob.constructQueueString(((DatabaseAttachment) slide.asAttachment()).attachmentId);
|
||||
jobManager.cancelAllInQueue(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PlayVideoClickListener implements SlideClickListener {
|
||||
private static final float MINIMUM_DOWNLOADED_THRESHOLD = 0.05f;
|
||||
private View parentView;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
package org.thoughtcrime.securesms.conversation.clicklisteners
|
||||
|
||||
import android.view.View
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentCompressionJob
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob
|
||||
import org.thoughtcrime.securesms.mms.Slide
|
||||
import org.thoughtcrime.securesms.mms.SlidesClickedListener
|
||||
|
||||
internal class AttachmentCancelClickListener : SlidesClickedListener {
|
||||
override fun onClick(v: View, slides: List<Slide>) {
|
||||
Log.i(TAG, "Canceling compression/upload/download jobs for ${slides.size} items")
|
||||
val jobManager = ApplicationDependencies.getJobManager()
|
||||
var cancelCount = 0
|
||||
for (slide in slides) {
|
||||
val attachmentId = (slide.asAttachment() as DatabaseAttachment).attachmentId
|
||||
val jobsToCancel = jobManager.find {
|
||||
when (it.factoryKey) {
|
||||
AttachmentDownloadJob.KEY -> AttachmentDownloadJob.jobSpecMatchesAttachmentId(it, attachmentId)
|
||||
AttachmentCompressionJob.KEY -> AttachmentCompressionJob.jobSpecMatchesAttachmentId(it, attachmentId)
|
||||
AttachmentUploadJob.KEY -> AttachmentUploadJob.jobSpecMatchesAttachmentId(it, attachmentId)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
jobsToCancel.forEach {
|
||||
jobManager.cancel(it.id)
|
||||
cancelCount++
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "Canceled $cancelCount jobs.")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(AttachmentCancelClickListener::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.clicklisteners
|
||||
|
||||
import android.view.View
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.mms.Slide
|
||||
import org.thoughtcrime.securesms.mms.SlidesClickedListener
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
|
||||
class ResendClickListener(private val messageRecord: MessageRecord) : SlidesClickedListener {
|
||||
override fun onClick(v: View?, slides: MutableList<Slide>?) {
|
||||
if (v == null) {
|
||||
Log.w(TAG, "Could not resend message, view was null!")
|
||||
return
|
||||
}
|
||||
|
||||
MessageSender.resend(v.context, messageRecord)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(ResendClickListener::class.java)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import androidx.media3.common.MimeTypes;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@@ -23,9 +22,10 @@ import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.mms.MediaStream;
|
||||
@@ -124,6 +124,21 @@ public final class AttachmentCompressionJob extends BaseJob {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
Log.i(TAG, "onAdded() " + attachmentId.toString());
|
||||
|
||||
final AttachmentTable database = SignalDatabase.attachments();
|
||||
final DatabaseAttachment attachment = database.getAttachment(attachmentId);
|
||||
final boolean pending = attachment != null && attachment.transferState != AttachmentTable.TRANSFER_PROGRESS_DONE
|
||||
&& attachment.transferState != AttachmentTable.TRANSFER_PROGRESS_PERMANENT_FAILURE;
|
||||
|
||||
if (pending) {
|
||||
Log.i(TAG, "onAdded() Marking attachment progress as 'started'");
|
||||
database.setTransferState(attachment.mmsId, attachmentId, AttachmentTable.TRANSFER_PROGRESS_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws Exception {
|
||||
Log.d(TAG, "Running for: " + attachmentId);
|
||||
@@ -147,7 +162,20 @@ public final class AttachmentCompressionJob extends BaseJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() { }
|
||||
public void onFailure() {
|
||||
AttachmentTable database = SignalDatabase.attachments();
|
||||
DatabaseAttachment databaseAttachment = database.getAttachment(attachmentId);
|
||||
if (databaseAttachment == null) {
|
||||
Log.i(TAG, "Could not find attachment in DB for compression job upon failure.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
database.setTransferProgressFailed(attachmentId, databaseAttachment.mmsId);
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, "Error marking attachment as failed upon failed compression.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onShouldRetry(@NonNull Exception exception) {
|
||||
@@ -352,6 +380,21 @@ public final class AttachmentCompressionJob extends BaseJob {
|
||||
result.getHeight());
|
||||
}
|
||||
|
||||
public static boolean jobSpecMatchesAttachmentId(@NonNull JobSpec jobSpec, @NonNull AttachmentId attachmentId) {
|
||||
if (!KEY.equals(jobSpec.getFactoryKey())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final byte[] serializedData = jobSpec.getSerializedData();
|
||||
if (serializedData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonJobData data = JsonJobData.deserialize(serializedData);
|
||||
final AttachmentId parsed = new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID));
|
||||
return attachmentId.equals(parsed);
|
||||
}
|
||||
|
||||
public static final class Factory implements Job.Factory<AttachmentCompressionJob> {
|
||||
@Override
|
||||
public @NonNull AttachmentCompressionJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobLogger;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId;
|
||||
import org.thoughtcrime.securesms.releasechannel.ReleaseChannel;
|
||||
@@ -63,10 +64,10 @@ public final class AttachmentDownloadJob extends BaseJob {
|
||||
|
||||
private static final String TAG = Log.tag(AttachmentDownloadJob.class);
|
||||
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_PART_ROW_ID = "part_row_id";
|
||||
private static final String KEY_PAR_UNIQUE_ID = "part_unique_id";
|
||||
private static final String KEY_MANUAL = "part_manual";
|
||||
private static final String KEY_MESSAGE_ID = "message_id";
|
||||
private static final String KEY_ROW_ID = "part_row_id";
|
||||
private static final String KEY_UNIQUE_ID = "part_unique_id";
|
||||
private static final String KEY_MANUAL = "part_manual";
|
||||
|
||||
private final long messageId;
|
||||
private final long partRowId;
|
||||
@@ -97,8 +98,8 @@ public final class AttachmentDownloadJob extends BaseJob {
|
||||
@Override
|
||||
public @Nullable byte[] serialize() {
|
||||
return new JsonJobData.Builder().putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putLong(KEY_PART_ROW_ID, partRowId)
|
||||
.putLong(KEY_PAR_UNIQUE_ID, partUniqueId)
|
||||
.putLong(KEY_ROW_ID, partRowId)
|
||||
.putLong(KEY_UNIQUE_ID, partUniqueId)
|
||||
.putBoolean(KEY_MANUAL, manual)
|
||||
.serialize();
|
||||
}
|
||||
@@ -318,6 +319,21 @@ public final class AttachmentDownloadJob extends BaseJob {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean jobSpecMatchesAttachmentId(@NonNull JobSpec jobSpec, @NonNull AttachmentId attachmentId) {
|
||||
if (!KEY.equals(jobSpec.getFactoryKey())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final byte[] serializedData = jobSpec.getSerializedData();
|
||||
if (serializedData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonJobData data = JsonJobData.deserialize(serializedData);
|
||||
final AttachmentId parsed = new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID));
|
||||
return attachmentId.equals(parsed);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class InvalidPartException extends Exception {
|
||||
InvalidPartException(String s) {super(s);}
|
||||
@@ -331,7 +347,7 @@ public final class AttachmentDownloadJob extends BaseJob {
|
||||
|
||||
return new AttachmentDownloadJob(parameters,
|
||||
data.getLong(KEY_MESSAGE_ID),
|
||||
new AttachmentId(data.getLong(KEY_PART_ROW_ID), data.getLong(KEY_PAR_UNIQUE_ID)),
|
||||
new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID)),
|
||||
data.getBoolean(KEY_MANUAL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,15 @@ import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||
import org.thoughtcrime.securesms.attachments.PointerAttachment
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHashEncoder
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec
|
||||
import org.thoughtcrime.securesms.jobs.protos.AttachmentUploadJobData
|
||||
import org.thoughtcrime.securesms.mms.MmsException
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
@@ -71,6 +74,17 @@ class AttachmentUploadJob private constructor(
|
||||
val maxPaddedSize = AttachmentCipherStreamUtil.getPlaintextLength(maxCipherTextSize)
|
||||
return PaddingInputStream.getMaxUnpaddedSize(maxPaddedSize)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun jobSpecMatchesAttachmentId(jobSpec: JobSpec, attachmentId: AttachmentId): Boolean {
|
||||
if (KEY != jobSpec.factoryKey) {
|
||||
return false
|
||||
}
|
||||
val serializedData = jobSpec.serializedData ?: return false
|
||||
val data = AttachmentUploadJobData.ADAPTER.decode(serializedData)
|
||||
val parsed = AttachmentId(data.attachmentRowId, data.attachmentUniqueId)
|
||||
return attachmentId == parsed
|
||||
}
|
||||
}
|
||||
|
||||
constructor(attachmentId: AttachmentId) : this(
|
||||
@@ -95,6 +109,25 @@ class AttachmentUploadJob private constructor(
|
||||
|
||||
override fun shouldTrace(): Boolean = true
|
||||
|
||||
override fun onAdded() {
|
||||
Log.i(TAG, "onAdded() $attachmentId")
|
||||
|
||||
val database = SignalDatabase.attachments
|
||||
val attachment = database.getAttachment(attachmentId)
|
||||
|
||||
if (attachment == null) {
|
||||
Log.w(TAG, "Could not fetch attachment from database.")
|
||||
return
|
||||
}
|
||||
|
||||
val pending = attachment.transferState != AttachmentTable.TRANSFER_PROGRESS_DONE && attachment.transferState != AttachmentTable.TRANSFER_PROGRESS_PERMANENT_FAILURE
|
||||
|
||||
if (pending) {
|
||||
Log.i(TAG, "onAdded() Marking attachment progress as 'started'")
|
||||
database.setTransferState(attachment.mmsId, attachmentId, AttachmentTable.TRANSFER_PROGRESS_STARTED)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
public override fun onRun() {
|
||||
if (!Recipient.self().isRegistered) {
|
||||
@@ -152,8 +185,17 @@ class AttachmentUploadJob private constructor(
|
||||
}
|
||||
|
||||
override fun onFailure() {
|
||||
if (isCanceled) {
|
||||
SignalDatabase.attachments.deleteAttachment(attachmentId)
|
||||
val database = SignalDatabase.attachments
|
||||
val databaseAttachment = database.getAttachment(attachmentId)
|
||||
if (databaseAttachment == null) {
|
||||
Log.i(TAG, "Could not find attachment in DB for upload job upon failure/cancellation.")
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
database.setTransferProgressFailed(attachmentId, databaseAttachment.mmsId)
|
||||
} catch (e: MmsException) {
|
||||
Log.w(TAG, "Error marking attachment as failed upon failed/canceled upload.", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ public class MediaUploadRepository {
|
||||
if (result != null) {
|
||||
Stream.of(result.getJobIds()).forEach(jobManager::cancel);
|
||||
uploadResults.remove(media);
|
||||
SignalDatabase.attachments().deleteAttachment(result.getAttachmentId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user