mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
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:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user