Fix stub of TransferControlsView.
This commit is contained in:
parent
1b49b9bffb
commit
5cf937215a
7 changed files with 188 additions and 59 deletions
|
@ -4,6 +4,8 @@ import android.content.Context;
|
|||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -22,6 +24,7 @@ import org.thoughtcrime.securesms.mms.ImageSlide;
|
|||
import org.thoughtcrime.securesms.mms.SlidesClickedListener;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -34,11 +37,14 @@ import okhttp3.HttpUrl;
|
|||
*/
|
||||
public class LinkPreviewView extends FrameLayout {
|
||||
|
||||
private static final String STATE_ROOT = "linkPreviewView.state.root";
|
||||
private static final String STATE_STATE = "linkPreviewView.state.state";
|
||||
|
||||
private static final int TYPE_CONVERSATION = 0;
|
||||
private static final int TYPE_COMPOSE = 1;
|
||||
|
||||
private ViewGroup container;
|
||||
private OutlinedThumbnailView thumbnail;
|
||||
private Stub<OutlinedThumbnailView> thumbnail;
|
||||
private TextView title;
|
||||
private TextView description;
|
||||
private TextView site;
|
||||
|
@ -51,6 +57,7 @@ public class LinkPreviewView extends FrameLayout {
|
|||
private int defaultRadius;
|
||||
private CornerMask cornerMask;
|
||||
private CloseClickedListener closeClickedListener;
|
||||
private LinkPreviewViewThumbnailState thumbnailState = new LinkPreviewViewThumbnailState();
|
||||
|
||||
public LinkPreviewView(Context context) {
|
||||
super(context);
|
||||
|
@ -66,7 +73,7 @@ public class LinkPreviewView extends FrameLayout {
|
|||
inflate(getContext(), R.layout.link_preview, this);
|
||||
|
||||
container = findViewById(R.id.linkpreview_container);
|
||||
thumbnail = findViewById(R.id.linkpreview_thumbnail);
|
||||
thumbnail = new Stub<>(findViewById(R.id.linkpreview_thumbnail));
|
||||
title = findViewById(R.id.linkpreview_title);
|
||||
description = findViewById(R.id.linkpreview_description);
|
||||
site = findViewById(R.id.linkpreview_site);
|
||||
|
@ -101,6 +108,30 @@ public class LinkPreviewView extends FrameLayout {
|
|||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull Parcelable onSaveInstanceState() {
|
||||
Parcelable root = super.onSaveInstanceState();
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
bundle.putParcelable(STATE_ROOT, root);
|
||||
bundle.putParcelable(STATE_STATE, thumbnailState);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
Parcelable root = ((Bundle) state).getParcelable(STATE_ROOT);
|
||||
thumbnailState = ((Bundle) state).getParcelable(STATE_STATE);
|
||||
|
||||
thumbnailState.applyState(thumbnail);
|
||||
super.onRestoreInstanceState(root);
|
||||
} else {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
@ -173,8 +204,9 @@ public class LinkPreviewView extends FrameLayout {
|
|||
|
||||
if (showThumbnail && linkPreview.getThumbnail().isPresent()) {
|
||||
thumbnail.setVisibility(VISIBLE);
|
||||
thumbnail.setImageResource(glideRequests, new ImageSlide(getContext(), linkPreview.getThumbnail().get()), type == TYPE_CONVERSATION, false);
|
||||
thumbnail.showDownloadText(false);
|
||||
thumbnailState.applyState(thumbnail);
|
||||
thumbnail.get().setImageResource(glideRequests, new ImageSlide(getContext(), linkPreview.getThumbnail().get()), type == TYPE_CONVERSATION, false);
|
||||
thumbnail.get().showDownloadText(false);
|
||||
} else {
|
||||
thumbnail.setVisibility(GONE);
|
||||
}
|
||||
|
@ -183,10 +215,24 @@ public class LinkPreviewView extends FrameLayout {
|
|||
public void setCorners(int topStart, int topEnd) {
|
||||
if (ViewUtil.isRtl(this)) {
|
||||
cornerMask.setRadii(topEnd, topStart, 0, 0);
|
||||
thumbnail.setCorners(defaultRadius, topEnd, defaultRadius, defaultRadius);
|
||||
thumbnailState = thumbnailState.copy(
|
||||
defaultRadius,
|
||||
topEnd,
|
||||
defaultRadius,
|
||||
defaultRadius,
|
||||
thumbnailState.getDownloadListener()
|
||||
);
|
||||
thumbnailState.applyState(thumbnail);
|
||||
} else {
|
||||
cornerMask.setRadii(topStart, topEnd, 0, 0);
|
||||
thumbnail.setCorners(topStart, defaultRadius, defaultRadius, defaultRadius);
|
||||
thumbnailState.copy(
|
||||
topStart,
|
||||
defaultRadius,
|
||||
defaultRadius,
|
||||
defaultRadius,
|
||||
thumbnailState.getDownloadListener()
|
||||
);
|
||||
thumbnailState.applyState(thumbnail);
|
||||
}
|
||||
postInvalidate();
|
||||
}
|
||||
|
@ -196,7 +242,8 @@ public class LinkPreviewView extends FrameLayout {
|
|||
}
|
||||
|
||||
public void setDownloadClickedListener(SlidesClickedListener listener) {
|
||||
thumbnail.setDownloadClickListener(listener);
|
||||
thumbnailState = thumbnailState.withDownloadListener(listener);
|
||||
thumbnailState.applyState(thumbnail);
|
||||
}
|
||||
|
||||
private @StringRes static int getLinkPreviewErrorString(@Nullable LinkPreviewRepository.Error customError) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.thoughtcrime.securesms.mms.SlidesClickedListener
|
||||
import org.thoughtcrime.securesms.util.views.Stub
|
||||
|
||||
@Parcelize
|
||||
data class LinkPreviewViewThumbnailState(
|
||||
val cornerTopLeft: Int = 0,
|
||||
val cornerTopRight: Int = 0,
|
||||
val cornerBottomRight: Int = 0,
|
||||
val cornerBottomLeft: Int = 0,
|
||||
@IgnoredOnParcel
|
||||
val downloadListener: SlidesClickedListener? = null
|
||||
) : Parcelable {
|
||||
fun withDownloadListener(downloadListener: SlidesClickedListener?): LinkPreviewViewThumbnailState {
|
||||
return copy(downloadListener = downloadListener)
|
||||
}
|
||||
|
||||
fun applyState(thumbnail: Stub<OutlinedThumbnailView>) {
|
||||
if (thumbnail.resolved()) {
|
||||
thumbnail.get().setCorners(cornerTopLeft, cornerTopRight, cornerBottomRight, cornerBottomLeft)
|
||||
thumbnail.get().setDownloadClickListener(downloadListener)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.util.Util;
|
|||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
@ -79,8 +80,8 @@ public class ThumbnailView extends FrameLayout {
|
|||
|
||||
private final CornerMask cornerMask;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private Optional<TransferControlView> transferControls = Optional.empty();
|
||||
private ThumbnailViewTransferControlsState transferControlsState = new ThumbnailViewTransferControlsState();
|
||||
private Stub<TransferControlView> transferControlViewStub;
|
||||
private SlideClickListener thumbnailClickListener = null;
|
||||
private SlidesClickedListener downloadClickListener = null;
|
||||
private Slide slide = null;
|
||||
|
@ -105,6 +106,7 @@ public class ThumbnailView extends FrameLayout {
|
|||
this.captionIcon = findViewById(R.id.thumbnail_caption_icon);
|
||||
this.errorImage = findViewById(R.id.thumbnail_error);
|
||||
this.cornerMask = new CornerMask(this);
|
||||
this.transferControlViewStub = new Stub<>(findViewById(R.id.transfer_controls_stub));
|
||||
|
||||
super.setOnClickListener(new ThumbnailClickDispatcher());
|
||||
|
||||
|
@ -275,26 +277,21 @@ public class ThumbnailView extends FrameLayout {
|
|||
@Override
|
||||
public void setFocusable(boolean focusable) {
|
||||
super.setFocusable(focusable);
|
||||
transferControls.ifPresent(transferControlView -> transferControlView.setFocusable(focusable));
|
||||
transferControlsState = transferControlsState.withFocusable(focusable);
|
||||
transferControlsState.applyState(transferControlViewStub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClickable(boolean clickable) {
|
||||
super.setClickable(clickable);
|
||||
transferControls.ifPresent(transferControlView -> transferControlView.setClickable(clickable));
|
||||
transferControlsState = transferControlsState.withClickable(clickable);
|
||||
transferControlsState.applyState(transferControlViewStub);
|
||||
}
|
||||
|
||||
public @Nullable Drawable getImageDrawable() {
|
||||
return image.getDrawable();
|
||||
}
|
||||
|
||||
private TransferControlView getTransferControls() {
|
||||
if (!transferControls.isPresent()) {
|
||||
transferControls = Optional.of(ViewUtil.inflateStub(this, R.id.transfer_controls_stub));
|
||||
}
|
||||
return transferControls.get();
|
||||
}
|
||||
|
||||
public void setBounds(int minWidth, int maxWidth, int minHeight, int maxHeight) {
|
||||
bounds[MIN_WIDTH] = minWidth;
|
||||
bounds[MAX_WIDTH] = maxWidth;
|
||||
|
@ -327,7 +324,7 @@ public class ThumbnailView extends FrameLayout {
|
|||
if (slide.asAttachment().isPermanentlyFailed()) {
|
||||
this.slide = slide;
|
||||
|
||||
transferControls.ifPresent(c -> c.setVisibility(View.GONE));
|
||||
transferControlViewStub.setVisibility(View.GONE);
|
||||
playOverlay.setVisibility(View.GONE);
|
||||
|
||||
glideRequests.clear(blurHash);
|
||||
|
@ -353,10 +350,18 @@ public class ThumbnailView extends FrameLayout {
|
|||
}
|
||||
|
||||
if (showControls) {
|
||||
getTransferControls().setSlide(slide);
|
||||
getTransferControls().setDownloadClickListener(new DownloadClickDispatcher());
|
||||
} else if (transferControls.isPresent()) {
|
||||
getTransferControls().setVisibility(View.GONE);
|
||||
int transferState = TransferControlView.getTransferState(Collections.singletonList(slide));
|
||||
if (transferState == AttachmentTable.TRANSFER_PROGRESS_DONE || transferState == AttachmentTable.TRANSFER_PROGRESS_PERMANENT_FAILURE) {
|
||||
transferControlViewStub.setVisibility(View.GONE);
|
||||
} else {
|
||||
transferControlViewStub.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
transferControlsState = transferControlsState.withSlide(slide)
|
||||
.withDownloadClickListener(new DownloadClickDispatcher());
|
||||
transferControlsState.applyState(transferControlViewStub);
|
||||
} else {
|
||||
transferControlViewStub.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (slide.getUri() != null && slide.hasPlayOverlay() &&
|
||||
|
@ -440,7 +445,7 @@ public class ThumbnailView extends FrameLayout {
|
|||
public ListenableFuture<Boolean> setImageResource(@NonNull GlideRequests glideRequests, @NonNull Uri uri, int width, int height, boolean animate, @Nullable ThumbnailRequestListener listener) {
|
||||
SettableFuture<Boolean> future = new SettableFuture<>();
|
||||
|
||||
if (transferControls.isPresent()) getTransferControls().setVisibility(View.GONE);
|
||||
transferControlViewStub.setVisibility(View.GONE);
|
||||
|
||||
GlideRequest<Drawable> request = glideRequests.load(new DecryptableUri(uri))
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
|
@ -473,7 +478,7 @@ public class ThumbnailView extends FrameLayout {
|
|||
public ListenableFuture<Boolean> setImageResource(@NonNull GlideRequests glideRequests, @NonNull StoryTextPostModel model, int width, int height) {
|
||||
SettableFuture<Boolean> future = new SettableFuture<>();
|
||||
|
||||
if (transferControls.isPresent()) getTransferControls().setVisibility(View.GONE);
|
||||
transferControlViewStub.setVisibility(View.GONE);
|
||||
|
||||
GlideRequest<Drawable> request = glideRequests.load(model)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
|
@ -502,8 +507,8 @@ public class ThumbnailView extends FrameLayout {
|
|||
glideRequests.clear(image);
|
||||
image.setImageDrawable(null);
|
||||
|
||||
if (transferControls.isPresent()) {
|
||||
getTransferControls().clear();
|
||||
if (transferControlViewStub.resolved()) {
|
||||
transferControlViewStub.get().clear();
|
||||
}
|
||||
|
||||
glideRequests.clear(blurHash);
|
||||
|
@ -513,11 +518,12 @@ public class ThumbnailView extends FrameLayout {
|
|||
}
|
||||
|
||||
public void showDownloadText(boolean showDownloadText) {
|
||||
getTransferControls().setShowDownloadText(showDownloadText);
|
||||
transferControlsState = transferControlsState.withDownloadText(showDownloadText);
|
||||
transferControlsState.applyState(transferControlViewStub);
|
||||
}
|
||||
|
||||
public void showProgressSpinner() {
|
||||
getTransferControls().showProgressSpinner();
|
||||
transferControlViewStub.get().showProgressSpinner();
|
||||
}
|
||||
|
||||
public void setScaleType(@NonNull ImageView.ScaleType scaleType) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.view.View.OnClickListener
|
||||
import org.thoughtcrime.securesms.mms.Slide
|
||||
import org.thoughtcrime.securesms.util.views.Stub
|
||||
|
||||
/**
|
||||
* State object for transfer controls.
|
||||
*/
|
||||
data class ThumbnailViewTransferControlsState(
|
||||
val isFocusable: Boolean = true,
|
||||
val isClickable: Boolean = true,
|
||||
val slide: Slide? = null,
|
||||
val downloadClickedListener: OnClickListener? = null,
|
||||
val showDownloadText: Boolean = true
|
||||
) {
|
||||
|
||||
fun withFocusable(isFocusable: Boolean): ThumbnailViewTransferControlsState = copy(isFocusable = isFocusable)
|
||||
fun withClickable(isClickable: Boolean): ThumbnailViewTransferControlsState = copy(isClickable = isClickable)
|
||||
fun withSlide(slide: Slide?): ThumbnailViewTransferControlsState = copy(slide = slide)
|
||||
fun withDownloadClickListener(downloadClickedListener: OnClickListener): ThumbnailViewTransferControlsState = copy(downloadClickedListener = downloadClickedListener)
|
||||
fun withDownloadText(showDownloadText: Boolean): ThumbnailViewTransferControlsState = copy(showDownloadText = showDownloadText)
|
||||
|
||||
fun applyState(transferControlView: Stub<TransferControlView>) {
|
||||
if (transferControlView.resolved()) {
|
||||
transferControlView.get().isFocusable = isFocusable
|
||||
transferControlView.get().isClickable = isClickable
|
||||
if (slide != null) {
|
||||
transferControlView.get().setSlide(slide)
|
||||
}
|
||||
transferControlView.get().setDownloadClickListener(downloadClickedListener)
|
||||
transferControlView.get().setShowDownloadText(showDownloadText)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -182,7 +182,7 @@ public final class TransferControlView extends FrameLayout {
|
|||
return true;
|
||||
}
|
||||
|
||||
private int getTransferState(@NonNull List<Slide> slides) {
|
||||
static int getTransferState(@NonNull List<Slide> slides) {
|
||||
int transferState = AttachmentTable.TRANSFER_PROGRESS_DONE;
|
||||
boolean allFailed = true;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/linkpreview_container"
|
||||
|
@ -11,19 +11,16 @@
|
|||
android:background="@color/signal_neutralSurface"
|
||||
android:padding="6dp">
|
||||
|
||||
<org.thoughtcrime.securesms.components.OutlinedThumbnailView
|
||||
<ViewStub
|
||||
android:id="@+id/linkpreview_thumbnail"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout="@layout/link_preview_thumbnail_stub"
|
||||
android:maxHeight="72dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/linkpreview_divider"
|
||||
app:layout_constraintHeight_min="72dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/linkpreview_title"
|
||||
tools:src="@drawable/ic_contact_picture"
|
||||
tools:visibility="visible" />
|
||||
app:layout_constraintTop_toTopOf="@+id/linkpreview_title" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/linkpreview_title"
|
||||
|
|
16
app/src/main/res/layout/link_preview_thumbnail_stub.xml
Normal file
16
app/src/main/res/layout/link_preview_thumbnail_stub.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.thoughtcrime.securesms.components.OutlinedThumbnailView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linkpreview_thumbnail"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="0dp"
|
||||
android:maxHeight="72dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/linkpreview_divider"
|
||||
app:layout_constraintHeight_min="72dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/linkpreview_title"
|
||||
tools:src="@drawable/ic_contact_picture"
|
||||
tools:visibility="visible" />
|
Loading…
Add table
Reference in a new issue