Make view state of text send UI easier to reason about

and fix bugs with bomb badge and hint display
This commit is contained in:
Torsten Grote
2020-12-16 12:22:03 -03:00
parent 56705bde74
commit 814b2b2582
3 changed files with 68 additions and 40 deletions

View File

@@ -23,7 +23,7 @@ public class CompositeSendButton extends FrameLayout {
private final ImageView bombBadge; private final ImageView bombBadge;
private final ProgressBar progressBar; private final ProgressBar progressBar;
private boolean hasImageSupport = false, bombVisible = false; private boolean hasImageSupport = false;
public CompositeSendButton(@NonNull Context context, public CompositeSendButton(@NonNull Context context,
@Nullable AttributeSet attrs) { @Nullable AttributeSet attrs) {
@@ -75,7 +75,6 @@ public class CompositeSendButton extends FrameLayout {
} }
public void setBombVisible(boolean visible) { public void setBombVisible(boolean visible) {
bombVisible = visible;
bombBadge.setVisibility(visible ? VISIBLE : INVISIBLE); bombBadge.setVisibility(visible ? VISIBLE : INVISIBLE);
} }
@@ -86,7 +85,6 @@ public class CompositeSendButton extends FrameLayout {
sendButton.clearAnimation(); sendButton.clearAnimation();
sendButton.animate().alpha(0f).withEndAction(() -> { sendButton.animate().alpha(0f).withEndAction(() -> {
sendButton.setVisibility(INVISIBLE); sendButton.setVisibility(INVISIBLE);
bombBadge.setVisibility(INVISIBLE);
imageButton.setEnabled(true); imageButton.setEnabled(true);
}).start(); }).start();
imageButton.clearAnimation(); imageButton.clearAnimation();
@@ -97,9 +95,7 @@ public class CompositeSendButton extends FrameLayout {
sendButton.setEnabled(sendEnabled); sendButton.setEnabled(sendEnabled);
imageButton.setEnabled(false); imageButton.setEnabled(false);
sendButton.clearAnimation(); sendButton.clearAnimation();
sendButton.animate().alpha(1f).withEndAction(() -> { sendButton.animate().alpha(1f).start();
if (bombVisible) bombBadge.setVisibility(VISIBLE);
}).start();
imageButton.clearAnimation(); imageButton.clearAnimation();
imageButton.animate().alpha(0f).withEndAction(() -> imageButton.animate().alpha(0f).withEndAction(() ->
imageButton.setVisibility(INVISIBLE) imageButton.setVisibility(INVISIBLE)

View File

@@ -52,7 +52,6 @@ public class TextAttachmentController extends TextSendController
private final AttachmentManager attachmentManager; private final AttachmentManager attachmentManager;
private final List<Uri> imageUris = new ArrayList<>(); private final List<Uri> imageUris = new ArrayList<>();
private final CharSequence textHint;
private boolean loadingUris = false; private boolean loadingUris = false;
public TextAttachmentController(TextInputView v, ImagePreview imagePreview, public TextAttachmentController(TextInputView v, ImagePreview imagePreview,
@@ -66,23 +65,44 @@ public class TextAttachmentController extends TextSendController
sendButton = (CompositeSendButton) compositeSendButton; sendButton = (CompositeSendButton) compositeSendButton;
sendButton.setOnImageClickListener(view -> onImageButtonClicked()); sendButton.setOnImageClickListener(view -> onImageButtonClicked());
textHint = textInput.getHint();
} }
@Override @Override
protected void updateViewState() { protected void updateViewState() {
textInput.setEnabled(ready && !loadingUris); super.updateViewState();
boolean sendEnabled = ready && !loadingUris &&
(!textIsEmpty || canSendEmptyText());
if (loadingUris) { if (loadingUris) {
sendButton.showProgress(true); sendButton.showProgress(true);
} else if (imageUris.isEmpty()) { } else if (imageUris.isEmpty()) {
sendButton.showProgress(false); sendButton.showProgress(false);
sendButton.showImageButton(textIsEmpty, sendEnabled); sendButton.showImageButton(textIsEmpty, isSendButtonEnabled());
} else { } else {
sendButton.showProgress(false); sendButton.showProgress(false);
sendButton.showImageButton(false, sendEnabled); sendButton.showImageButton(false, isSendButtonEnabled());
}
}
@Override
protected boolean isTextInputEnabled() {
return super.isTextInputEnabled() && !loadingUris;
}
@Override
protected boolean isSendButtonEnabled() {
return super.isSendButtonEnabled() && !loadingUris;
}
@Override
protected boolean isBombVisible() {
return super.isBombVisible() && (!textIsEmpty || !imageUris.isEmpty());
}
@Override
protected CharSequence getCurrentTextHint() {
if (imageUris.isEmpty()) {
return super.getCurrentTextHint();
} else {
Context ctx = textInput.getContext();
return ctx.getString(R.string.image_caption_hint);
} }
} }
@@ -161,7 +181,6 @@ public class TextAttachmentController extends TextSendController
} }
imageUris.addAll(newUris); imageUris.addAll(newUris);
updateViewState(); updateViewState();
textInput.setHint(R.string.image_caption_hint);
List<ImagePreviewItem> items = ImagePreviewItem.fromUris(imageUris); List<ImagePreviewItem> items = ImagePreviewItem.fromUris(imageUris);
imagePreview.showPreview(items); imagePreview.showPreview(items);
// store attachments and show preview when successful // store attachments and show preview when successful
@@ -207,8 +226,6 @@ public class TextAttachmentController extends TextSendController
} }
private void reset() { private void reset() {
// restore hint
textInput.setHint(textHint);
// hide image layout // hide image layout
imagePreview.setVisibility(GONE); imagePreview.setVisibility(GONE);
// reset image URIs // reset image URIs

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.android.view; package org.briarproject.briar.android.view;
import android.content.Context;
import android.os.Parcelable; import android.os.Parcelable;
import android.view.View; import android.view.View;
@@ -7,12 +8,12 @@ import com.google.android.material.snackbar.Snackbar;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.conversation.ConversationActivity;
import org.briarproject.briar.android.view.EmojiTextInputView.TextInputListener; import org.briarproject.briar.android.view.EmojiTextInputView.TextInputListener;
import org.briarproject.briar.api.attachment.AttachmentHeader; import org.briarproject.briar.api.attachment.AttachmentHeader;
import java.util.List; import java.util.List;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
@@ -28,10 +29,12 @@ public class TextSendController implements TextInputListener {
protected final View compositeSendButton; protected final View compositeSendButton;
protected final SendListener listener; protected final SendListener listener;
protected boolean ready = true, textIsEmpty = true; protected boolean textIsEmpty = true;
private boolean ready = true;
private long currentTimer = NO_AUTO_DELETE_TIMER;
private final CharSequence defaultHint;
private final boolean allowEmptyText; private final boolean allowEmptyText;
private CharSequence defaultHint;
public TextSendController(TextInputView v, SendListener listener, public TextSendController(TextInputView v, SendListener listener,
boolean allowEmptyText) { boolean allowEmptyText) {
@@ -63,31 +66,43 @@ public class TextSendController implements TextInputListener {
/** /**
* Sets the current auto delete timer and updates the UI accordingly. * Sets the current auto delete timer and updates the UI accordingly.
* <p>
* Attention: Works only in {@link ConversationActivity}.
*/ */
public void setAutoDeleteTimer(long timer) { public void setAutoDeleteTimer(long timer) {
// this will need to be adapted when other screens currentTimer = timer;
// besides the private conversation use auto delete timers updateViewState();
CompositeSendButton sendButton = }
(CompositeSendButton) compositeSendButton;
// update hint @CallSuper
if (timer == NO_AUTO_DELETE_TIMER) { protected void updateViewState() {
textInput.setHint(defaultHint); textInput.setEnabled(isTextInputEnabled());
sendButton.setBombVisible(false); textInput.setHint(getCurrentTextHint());
} else { compositeSendButton.setEnabled(isSendButtonEnabled());
// this might need to be adapted when other screens if (compositeSendButton instanceof CompositeSendButton) {
// besides the private conversation use auto delete timers CompositeSendButton sendButton =
defaultHint = textInput.getHint(); (CompositeSendButton) compositeSendButton;
textInput.setHint(R.string.message_hint_auto_delete); sendButton.setBombVisible(isBombVisible());
sendButton.setBombVisible(true);
} }
} }
protected void updateViewState() { protected boolean isTextInputEnabled() {
textInput.setEnabled(ready); return ready;
compositeSendButton }
.setEnabled(ready && (!textIsEmpty || canSendEmptyText()));
protected boolean isSendButtonEnabled() {
return ready && (!textIsEmpty || canSendEmptyText());
}
protected boolean isBombVisible() {
return currentTimer != NO_AUTO_DELETE_TIMER;
}
protected CharSequence getCurrentTextHint() {
if (currentTimer == NO_AUTO_DELETE_TIMER) {
return defaultHint;
} else {
Context ctx = textInput.getContext();
return ctx.getString(R.string.message_hint_auto_delete);
}
} }
protected final boolean canSend() { protected final boolean canSend() {