mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 04:39:54 +01:00
[android] Show progress bar while image previews are loading
This refactors the send buttons out into their own composite view
This commit is contained in:
@@ -86,7 +86,7 @@ public class ReblogFragment extends BaseFragment implements SendListener {
|
|||||||
TextSendController sendController =
|
TextSendController sendController =
|
||||||
new TextSendController(ui.input, this, true);
|
new TextSendController(ui.input, this, true);
|
||||||
ui.input.setSendController(sendController);
|
ui.input.setSendController(sendController);
|
||||||
ui.input.setEnabled(false);
|
ui.input.setReady(false);
|
||||||
ui.input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH);
|
ui.input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH);
|
||||||
showProgressBar();
|
showProgressBar();
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ public class ReblogFragment extends BaseFragment implements SendListener {
|
|||||||
ui.post.bindItem(item);
|
ui.post.bindItem(item);
|
||||||
ui.post.hideReblogButton();
|
ui.post.hideReblogButton();
|
||||||
|
|
||||||
ui.input.setEnabled(true);
|
ui.input.setReady(true);
|
||||||
ui.scrollView.post(() -> ui.scrollView.fullScroll(FOCUS_DOWN));
|
ui.scrollView.post(() -> ui.scrollView.fullScroll(FOCUS_DOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public class WriteBlogPostActivity extends BriarActivity
|
|||||||
new TextSendController(input, this, false);
|
new TextSendController(input, this, false);
|
||||||
input.setSendController(sendController);
|
input.setSendController(sendController);
|
||||||
input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH);
|
input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH);
|
||||||
|
input.setReady(true);
|
||||||
|
|
||||||
progressBar = findViewById(R.id.progressBar);
|
progressBar = findViewById(R.id.progressBar);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
textInputView.setSendController(sendController);
|
textInputView.setSendController(sendController);
|
||||||
textInputView.setMaxTextLength(MAX_PRIVATE_MESSAGE_TEXT_LENGTH);
|
textInputView.setMaxTextLength(MAX_PRIVATE_MESSAGE_TEXT_LENGTH);
|
||||||
textInputView.setEnabled(false);
|
textInputView.setReady(false);
|
||||||
textInputView.addOnKeyboardShownListener(this::scrollToBottom);
|
textInputView.addOnKeyboardShownListener(this::scrollToBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +477,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
if (revision == adapter.getRevision()) {
|
if (revision == adapter.getRevision()) {
|
||||||
adapter.incrementRevision();
|
adapter.incrementRevision();
|
||||||
textInputView.setEnabled(true);
|
textInputView.setReady(true);
|
||||||
// start observing onboarding after enabling (only once, because
|
// start observing onboarding after enabling (only once, because
|
||||||
// we only update this when an onboarding should be shown)
|
// we only update this when an onboarding should be shown)
|
||||||
observeOnce(viewModel.showImageOnboarding(), this,
|
observeOnce(viewModel.showImageOnboarding(), this,
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
new TextSendController(ui.message, this, true);
|
new TextSendController(ui.message, this, true);
|
||||||
ui.message.setSendController(sendController);
|
ui.message.setSendController(sendController);
|
||||||
ui.message.setMaxTextLength(MAX_INTRODUCTION_TEXT_LENGTH);
|
ui.message.setMaxTextLength(MAX_INTRODUCTION_TEXT_LENGTH);
|
||||||
ui.message.setEnabled(false);
|
ui.message.setReady(false);
|
||||||
|
|
||||||
// get contacts and then show view
|
// get contacts and then show view
|
||||||
prepareToSetUpViews(contactId1, contactId2);
|
prepareToSetUpViews(contactId1, contactId2);
|
||||||
@@ -171,7 +171,7 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
// show views
|
// show views
|
||||||
ui.notPossible.setVisibility(GONE);
|
ui.notPossible.setVisibility(GONE);
|
||||||
ui.message.setVisibility(VISIBLE);
|
ui.message.setVisibility(VISIBLE);
|
||||||
ui.message.setEnabled(true);
|
ui.message.setReady(true);
|
||||||
ui.message.showSoftKeyboard();
|
ui.message.showSoftKeyboard();
|
||||||
} else {
|
} else {
|
||||||
ui.notPossible.setVisibility(VISIBLE);
|
ui.notPossible.setVisibility(VISIBLE);
|
||||||
@@ -195,7 +195,7 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onSendClick(@Nullable String text, List<Uri> imageUris) {
|
public void onSendClick(@Nullable String text, List<Uri> imageUris) {
|
||||||
// disable button to prevent accidental double invitations
|
// disable button to prevent accidental double invitations
|
||||||
ui.message.setEnabled(false);
|
ui.message.setReady(false);
|
||||||
|
|
||||||
makeIntroduction(contact1, contact2, text);
|
makeIntroduction(contact1, contact2, text);
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
new TextSendController(textInput, this, false);
|
new TextSendController(textInput, this, false);
|
||||||
textInput.setSendController(sendController);
|
textInput.setSendController(sendController);
|
||||||
textInput.setMaxTextLength(getMaxTextLength());
|
textInput.setMaxTextLength(getMaxTextLength());
|
||||||
|
textInput.setReady(true);
|
||||||
|
|
||||||
UnreadMessageButton upButton = findViewById(R.id.upButton);
|
UnreadMessageButton upButton = findViewById(R.id.upButton);
|
||||||
UnreadMessageButton downButton = findViewById(R.id.downButton);
|
UnreadMessageButton downButton = findViewById(R.id.downButton);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package org.briarproject.briar.android.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.widget.AppCompatImageButton;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class CompositeSendButton extends FrameLayout {
|
||||||
|
|
||||||
|
private final AppCompatImageButton sendButton, imageButton;
|
||||||
|
private final ProgressBar progressBar;
|
||||||
|
|
||||||
|
private boolean hasImageSupport = false;
|
||||||
|
|
||||||
|
public CompositeSendButton(@NonNull Context context,
|
||||||
|
@Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
LayoutInflater inflater = (LayoutInflater) requireNonNull(
|
||||||
|
context.getSystemService(LAYOUT_INFLATER_SERVICE));
|
||||||
|
inflater.inflate(R.layout.view_composite_send_button, this, true);
|
||||||
|
|
||||||
|
sendButton = findViewById(R.id.sendButton);
|
||||||
|
imageButton = findViewById(R.id.imageButton);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
setSendEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnClickListener(@Nullable View.OnClickListener l) {
|
||||||
|
setOnSendClickListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnSendClickListener(@Nullable OnClickListener l) {
|
||||||
|
sendButton.setOnClickListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSendEnabled(boolean enabled) {
|
||||||
|
sendButton.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnImageClickListener(@Nullable OnClickListener l) {
|
||||||
|
imageButton.setOnClickListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, image support is disabled.
|
||||||
|
* Once you know that it is supported in the current context,
|
||||||
|
* call this method to enable it.
|
||||||
|
*/
|
||||||
|
public void setImagesSupported() {
|
||||||
|
hasImageSupport = true;
|
||||||
|
imageButton.setImageResource(R.drawable.ic_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasImageSupport() {
|
||||||
|
return hasImageSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showImageButton(boolean showImageButton, boolean sendEnabled) {
|
||||||
|
if (showImageButton) {
|
||||||
|
imageButton.setVisibility(VISIBLE);
|
||||||
|
sendButton.setEnabled(false);
|
||||||
|
if (SDK_INT <= 15) {
|
||||||
|
sendButton.setVisibility(INVISIBLE);
|
||||||
|
imageButton.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
sendButton.clearAnimation();
|
||||||
|
sendButton.animate().alpha(0f).withEndAction(() -> {
|
||||||
|
sendButton.setVisibility(INVISIBLE);
|
||||||
|
imageButton.setEnabled(true);
|
||||||
|
}).start();
|
||||||
|
imageButton.clearAnimation();
|
||||||
|
imageButton.animate().alpha(1f).start();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendButton.setVisibility(VISIBLE);
|
||||||
|
// enable/disable buttons right away to allow fast sending
|
||||||
|
sendButton.setEnabled(sendEnabled);
|
||||||
|
imageButton.setEnabled(false);
|
||||||
|
if (SDK_INT <= 15) {
|
||||||
|
imageButton.setVisibility(INVISIBLE);
|
||||||
|
} else {
|
||||||
|
sendButton.clearAnimation();
|
||||||
|
sendButton.animate().alpha(1f).start();
|
||||||
|
imageButton.clearAnimation();
|
||||||
|
imageButton.animate().alpha(0f).withEndAction(() ->
|
||||||
|
imageButton.setVisibility(INVISIBLE)
|
||||||
|
).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showProgress(boolean show) {
|
||||||
|
sendButton.setVisibility(show ? INVISIBLE : VISIBLE);
|
||||||
|
imageButton.setVisibility(show ? INVISIBLE : VISIBLE);
|
||||||
|
progressBar.setVisibility(show ? VISIBLE : INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -65,7 +65,7 @@ public class LargeTextInputView extends TextInputView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setButtonText(String text) {
|
public void setButtonText(String text) {
|
||||||
((Button) findViewById(R.id.btn_send)).setText(text);
|
((Button) findViewById(R.id.compositeSendButton)).setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import android.support.annotation.Nullable;
|
|||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.v4.view.AbsSavedState;
|
import android.support.v4.view.AbsSavedState;
|
||||||
import android.support.v7.app.AlertDialog.Builder;
|
import android.support.v7.app.AlertDialog.Builder;
|
||||||
import android.support.v7.widget.AppCompatImageButton;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
@@ -32,8 +31,6 @@ import static android.os.Build.VERSION.SDK_INT;
|
|||||||
import static android.support.v4.content.ContextCompat.getColor;
|
import static android.support.v4.content.ContextCompat.getColor;
|
||||||
import static android.support.v4.view.AbsSavedState.EMPTY_STATE;
|
import static android.support.v4.view.AbsSavedState.EMPTY_STATE;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.INVISIBLE;
|
|
||||||
import static android.view.View.VISIBLE;
|
|
||||||
import static android.widget.Toast.LENGTH_LONG;
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
@@ -46,15 +43,14 @@ import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.S
|
|||||||
public class TextAttachmentController extends TextSendController
|
public class TextAttachmentController extends TextSendController
|
||||||
implements ImagePreviewListener {
|
implements ImagePreviewListener {
|
||||||
|
|
||||||
private final AppCompatImageButton imageButton;
|
|
||||||
private final ImagePreview imagePreview;
|
private final ImagePreview imagePreview;
|
||||||
|
|
||||||
private final AttachImageListener imageListener;
|
private final AttachImageListener imageListener;
|
||||||
|
private final CompositeSendButton sendButton;
|
||||||
|
|
||||||
private CharSequence textHint;
|
private CharSequence textHint;
|
||||||
private boolean hasImageSupport = false;
|
|
||||||
private List<Uri> imageUris = emptyList();
|
private List<Uri> imageUris = emptyList();
|
||||||
private int previewsLoaded = 0;
|
private int previewsLoaded = 0;
|
||||||
|
private boolean loadingPreviews = false;
|
||||||
|
|
||||||
public TextAttachmentController(TextInputView v, ImagePreview imagePreview,
|
public TextAttachmentController(TextInputView v, ImagePreview imagePreview,
|
||||||
SendListener listener, AttachImageListener imageListener) {
|
SendListener listener, AttachImageListener imageListener) {
|
||||||
@@ -63,18 +59,26 @@ public class TextAttachmentController extends TextSendController
|
|||||||
this.imagePreview = imagePreview;
|
this.imagePreview = imagePreview;
|
||||||
this.imagePreview.setImagePreviewListener(this);
|
this.imagePreview.setImagePreviewListener(this);
|
||||||
|
|
||||||
imageButton = v.findViewById(R.id.imageButton);
|
sendButton = (CompositeSendButton) compositeSendButton;
|
||||||
imageButton.setOnClickListener(view -> onImageButtonClicked());
|
sendButton.setOnImageClickListener(view -> onImageButtonClicked());
|
||||||
|
|
||||||
textHint = textInput.getHint();
|
textHint = textInput.getHint();
|
||||||
|
|
||||||
// show image button
|
|
||||||
showImageButton(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextIsEmptyChanged(boolean isEmpty) {
|
protected void updateViewState() {
|
||||||
if (imageUris.isEmpty()) showImageButton(isEmpty);
|
textInput.setEnabled(ready && !loadingPreviews);
|
||||||
|
boolean sendEnabled = ready && !loadingPreviews &&
|
||||||
|
(!textIsEmpty || canSendEmptyText());
|
||||||
|
if (loadingPreviews) {
|
||||||
|
sendButton.showProgress(true);
|
||||||
|
} else if (imageUris.isEmpty()) {
|
||||||
|
sendButton.showProgress(false);
|
||||||
|
sendButton.showImageButton(textIsEmpty, sendEnabled);
|
||||||
|
} else {
|
||||||
|
sendButton.showProgress(false);
|
||||||
|
sendButton.showImageButton(false, sendEnabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -90,19 +94,13 @@ public class TextAttachmentController extends TextSendController
|
|||||||
return !imageUris.isEmpty();
|
return !imageUris.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* By default, image support is disabled.
|
|
||||||
* Once you know that it is supported in the current context,
|
|
||||||
* call this method to enable it.
|
|
||||||
*/
|
|
||||||
public void setImagesSupported() {
|
public void setImagesSupported() {
|
||||||
hasImageSupport = true;
|
sendButton.setImagesSupported();
|
||||||
imageButton.setImageResource(R.drawable.ic_image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onImageButtonClicked() {
|
private void onImageButtonClicked() {
|
||||||
if (!hasImageSupport) {
|
if (!sendButton.hasImageSupport()) {
|
||||||
Context ctx = imageButton.getContext();
|
Context ctx = imagePreview.getContext();
|
||||||
Builder builder = new Builder(ctx, R.style.OnboardingDialogTheme);
|
Builder builder = new Builder(ctx, R.style.OnboardingDialogTheme);
|
||||||
builder.setTitle(
|
builder.setTitle(
|
||||||
ctx.getString(R.string.dialog_title_no_image_support));
|
ctx.getString(R.string.dialog_title_no_image_support));
|
||||||
@@ -138,45 +136,12 @@ public class TextAttachmentController extends TextSendController
|
|||||||
|
|
||||||
private void onNewUris() {
|
private void onNewUris() {
|
||||||
if (imageUris.isEmpty()) return;
|
if (imageUris.isEmpty()) return;
|
||||||
showImageButton(false);
|
loadingPreviews = true;
|
||||||
|
updateViewState();
|
||||||
textInput.setHint(R.string.image_caption_hint);
|
textInput.setHint(R.string.image_caption_hint);
|
||||||
imagePreview.showPreview(imageUris);
|
imagePreview.showPreview(imageUris);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showImageButton(boolean showImageButton) {
|
|
||||||
if (showImageButton) {
|
|
||||||
imageButton.setVisibility(VISIBLE);
|
|
||||||
sendButton.setEnabled(false);
|
|
||||||
if (SDK_INT <= 15) {
|
|
||||||
sendButton.setVisibility(INVISIBLE);
|
|
||||||
imageButton.setEnabled(true);
|
|
||||||
} else {
|
|
||||||
sendButton.clearAnimation();
|
|
||||||
sendButton.animate().alpha(0f).withEndAction(() -> {
|
|
||||||
sendButton.setVisibility(INVISIBLE);
|
|
||||||
imageButton.setEnabled(true);
|
|
||||||
}).start();
|
|
||||||
imageButton.clearAnimation();
|
|
||||||
imageButton.animate().alpha(1f).start();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendButton.setVisibility(VISIBLE);
|
|
||||||
// enable/disable buttons right away to allow fast sending
|
|
||||||
sendButton.setEnabled(enabled);
|
|
||||||
imageButton.setEnabled(false);
|
|
||||||
if (SDK_INT <= 15) {
|
|
||||||
imageButton.setVisibility(INVISIBLE);
|
|
||||||
} else {
|
|
||||||
sendButton.clearAnimation();
|
|
||||||
sendButton.animate().alpha(1f).start();
|
|
||||||
imageButton.clearAnimation();
|
|
||||||
imageButton.animate().alpha(0f).withEndAction(() ->
|
|
||||||
imageButton.setVisibility(INVISIBLE)
|
|
||||||
).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
// restore hint
|
// restore hint
|
||||||
textInput.setHint(textHint);
|
textInput.setHint(textHint);
|
||||||
@@ -184,10 +149,11 @@ public class TextAttachmentController extends TextSendController
|
|||||||
imagePreview.setVisibility(GONE);
|
imagePreview.setVisibility(GONE);
|
||||||
// reset image URIs
|
// reset image URIs
|
||||||
imageUris = emptyList();
|
imageUris = emptyList();
|
||||||
// show the image button again, so images can get attached
|
|
||||||
showImageButton(true);
|
|
||||||
// no preview has been loaded
|
// no preview has been loaded
|
||||||
previewsLoaded = 0;
|
previewsLoaded = 0;
|
||||||
|
loadingPreviews = false;
|
||||||
|
// show the image button again, so images can get attached
|
||||||
|
updateViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -230,14 +196,14 @@ public class TextAttachmentController extends TextSendController
|
|||||||
@Override
|
@Override
|
||||||
public void onCancel() {
|
public void onCancel() {
|
||||||
textInput.clearText();
|
textInput.clearText();
|
||||||
sendButton.setEnabled(true);
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAllPreviewsLoaded() {
|
private void checkAllPreviewsLoaded() {
|
||||||
if (previewsLoaded == imageUris.size()) {
|
if (previewsLoaded == imageUris.size()) {
|
||||||
|
loadingPreviews = false;
|
||||||
// all previews were loaded
|
// all previews were loaded
|
||||||
// TODO allow sending
|
updateViewState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +216,7 @@ public class TextAttachmentController extends TextSendController
|
|||||||
};
|
};
|
||||||
int color = resolveColorAttribute(activity, R.attr.colorControlNormal);
|
int color = resolveColorAttribute(activity, R.attr.colorControlNormal);
|
||||||
new MaterialTapTargetPrompt.Builder(activity,
|
new MaterialTapTargetPrompt.Builder(activity,
|
||||||
R.style.OnboardingDialogTheme).setTarget(imageButton)
|
R.style.OnboardingDialogTheme).setTarget(sendButton)
|
||||||
.setPrimaryText(R.string.dialog_title_image_support)
|
.setPrimaryText(R.string.dialog_title_image_support)
|
||||||
.setSecondaryText(R.string.dialog_message_image_support)
|
.setSecondaryText(R.string.dialog_message_image_support)
|
||||||
.setBackgroundColour(getColor(activity, R.color.briar_primary))
|
.setBackgroundColour(getColor(activity, R.color.briar_primary))
|
||||||
|
|||||||
@@ -99,9 +99,11 @@ public class TextInputView extends LinearLayout {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
super.setEnabled(enabled);
|
throw new RuntimeException("Use controllers to enable/disable");
|
||||||
textInput.setEnabled(enabled);
|
}
|
||||||
requireNonNull(textSendController).setEnabled(enabled);
|
|
||||||
|
public void setReady(boolean ready) {
|
||||||
|
requireNonNull(textSendController).setReady(ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.view;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.CallSuper;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
@@ -22,18 +21,17 @@ import static java.util.Collections.emptyList;
|
|||||||
public class TextSendController implements TextInputListener {
|
public class TextSendController implements TextInputListener {
|
||||||
|
|
||||||
protected final EmojiTextInputView textInput;
|
protected final EmojiTextInputView textInput;
|
||||||
protected final View sendButton;
|
protected final View compositeSendButton;
|
||||||
protected final SendListener listener;
|
protected final SendListener listener;
|
||||||
protected boolean enabled = true;
|
|
||||||
protected final boolean allowEmptyText;
|
|
||||||
|
|
||||||
private boolean wasEmpty = true;
|
protected boolean ready = true, textIsEmpty = true;
|
||||||
|
|
||||||
|
private final boolean allowEmptyText;
|
||||||
|
|
||||||
public TextSendController(TextInputView v, SendListener listener,
|
public TextSendController(TextInputView v, SendListener listener,
|
||||||
boolean allowEmptyText) {
|
boolean allowEmptyText) {
|
||||||
this.sendButton = v.findViewById(R.id.btn_send);
|
this.compositeSendButton = v.findViewById(R.id.compositeSendButton);
|
||||||
this.sendButton.setOnClickListener(view -> onSendEvent());
|
this.compositeSendButton.setOnClickListener(view -> onSendEvent());
|
||||||
this.sendButton.setEnabled(allowEmptyText);
|
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.textInput = v.getEmojiTextInputView();
|
this.textInput = v.getEmojiTextInputView();
|
||||||
this.allowEmptyText = allowEmptyText;
|
this.allowEmptyText = allowEmptyText;
|
||||||
@@ -41,8 +39,8 @@ public class TextSendController implements TextInputListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextIsEmptyChanged(boolean isEmpty) {
|
public void onTextIsEmptyChanged(boolean isEmpty) {
|
||||||
sendButton.setEnabled(enabled && (!isEmpty || canSendEmptyText()));
|
textIsEmpty = isEmpty;
|
||||||
wasEmpty = isEmpty;
|
updateViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,13 +50,24 @@ public class TextSendController implements TextInputListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setReady(boolean ready) {
|
||||||
|
this.ready = ready;
|
||||||
|
updateViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateViewState() {
|
||||||
|
textInput.setEnabled(ready);
|
||||||
|
compositeSendButton
|
||||||
|
.setEnabled(ready && (!textIsEmpty || canSendEmptyText()));
|
||||||
|
}
|
||||||
|
|
||||||
protected final boolean canSend() {
|
protected final boolean canSend() {
|
||||||
if (textInput.isTooLong()) {
|
if (textInput.isTooLong()) {
|
||||||
Snackbar.make(sendButton, R.string.text_too_long, LENGTH_SHORT)
|
Snackbar.make(compositeSendButton, R.string.text_too_long,
|
||||||
.show();
|
LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return enabled && (canSendEmptyText() || !textInput.isEmpty());
|
return ready && (canSendEmptyText() || !textInput.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canSendEmptyText() {
|
protected boolean canSendEmptyText() {
|
||||||
@@ -75,12 +84,6 @@ public class TextSendController implements TextInputListener {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
sendButton.setEnabled(enabled && (!wasEmpty || canSendEmptyText()));
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SendListener {
|
public interface SendListener {
|
||||||
void onSendClick(@Nullable String text, List<Uri> imageUris);
|
void onSendClick(@Nullable String text, List<Uri> imageUris);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,41 +24,11 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
app:maxTextLines="4"/>
|
app:maxTextLines="4"/>
|
||||||
|
|
||||||
<FrameLayout
|
<org.briarproject.briar.android.view.CompositeSendButton
|
||||||
|
android:id="@+id/compositeSendButton"
|
||||||
android:layout_width="@dimen/text_input_height"
|
android:layout_width="@dimen/text_input_height"
|
||||||
android:layout_height="@dimen/text_input_height"
|
android:layout_height="@dimen/text_input_height"
|
||||||
android:layout_gravity="bottom">
|
android:layout_gravity="bottom"/>
|
||||||
|
|
||||||
<android.support.v7.widget.AppCompatImageButton
|
|
||||||
android:id="@+id/imageButton"
|
|
||||||
android:layout_width="@dimen/text_input_height"
|
|
||||||
android:layout_height="@dimen/text_input_height"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:contentDescription="@string/image_attach"
|
|
||||||
android:enabled="false"
|
|
||||||
android:focusable="true"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="center"
|
|
||||||
android:src="@drawable/ic_image_off"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:tint="?attr/colorControlNormal"/>
|
|
||||||
|
|
||||||
<android.support.v7.widget.AppCompatImageButton
|
|
||||||
android:id="@+id/btn_send"
|
|
||||||
android:layout_width="@dimen/text_input_height"
|
|
||||||
android:layout_height="@dimen/text_input_height"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:contentDescription="@string/send"
|
|
||||||
android:enabled="false"
|
|
||||||
android:focusable="true"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:scaleType="center"
|
|
||||||
android:src="@drawable/social_send_now_white"
|
|
||||||
app:tint="@color/briar_accent"/>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
</android.support.v7.widget.CardView>
|
</android.support.v7.widget.CardView>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_send"
|
android:id="@+id/compositeSendButton"
|
||||||
style="@style/BriarButton"
|
style="@style/BriarButton"
|
||||||
android:layout_marginEnd="@dimen/margin_small"
|
android:layout_marginEnd="@dimen/margin_small"
|
||||||
android:layout_marginLeft="@dimen/margin_small"
|
android:layout_marginLeft="@dimen/margin_small"
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?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"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="@dimen/text_input_height"
|
||||||
|
android:layout_height="@dimen/text_input_height"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
tools:parentTag="org.briarproject.briar.android.view.CompositeSendButton"
|
||||||
|
tools:showIn="@layout/text_input_view">
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatImageButton
|
||||||
|
android:id="@+id/imageButton"
|
||||||
|
android:layout_width="@dimen/text_input_height"
|
||||||
|
android:layout_height="@dimen/text_input_height"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/image_attach"
|
||||||
|
android:enabled="false"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/ic_image_off"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:tint="?attr/colorControlNormal"/>
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatImageButton
|
||||||
|
android:id="@+id/sendButton"
|
||||||
|
android:layout_width="@dimen/text_input_height"
|
||||||
|
android:layout_height="@dimen/text_input_height"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/send"
|
||||||
|
android:enabled="false"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/social_send_now_white"
|
||||||
|
app:tint="@color/briar_accent"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="@dimen/text_input_height"
|
||||||
|
android:layout_height="@dimen/text_input_height"
|
||||||
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
|
</merge>
|
||||||
Reference in New Issue
Block a user