diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java index 94f75cb8c52631ac0772a69e64a8f115ce89a82d..190d957b7123e04067d6a5672ff6ac4e5f35007f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java @@ -20,6 +20,7 @@ import org.briarproject.briar.android.controller.handler.UiResultExceptionHandle import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import java.util.List; @@ -81,6 +82,9 @@ public class ReblogFragment extends BaseFragment implements SendListener { View v = inflater.inflate(R.layout.fragment_reblog, container, false); ui = new ViewHolder(v); ui.post.setTransitionName(postId); + TextSendController sendController = + new TextSendController(ui.input, this, true); + ui.input.setSendController(sendController); ui.input.setEnabled(false); ui.input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH); showProgressBar(); @@ -117,7 +121,6 @@ public class ReblogFragment extends BaseFragment implements SendListener { ui.post.bindItem(item); ui.post.hideReblogButton(); - ui.input.setListener(this); ui.input.setEnabled(true); ui.scrollView.post(() -> ui.scrollView.fullScroll(FOCUS_DOWN)); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java index e26e2e05e2bbc1cac575a2d0fdb3ebc1a5485db1..e67fc2a6968d06b3d2c5b90f8c16b8600f6841f2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java @@ -22,6 +22,7 @@ import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogPost; @@ -75,8 +76,10 @@ public class WriteBlogPostActivity extends BriarActivity setContentView(R.layout.activity_write_blog_post); input = findViewById(R.id.textInput); + TextSendController sendController = + new TextSendController(input, this, false); + input.setSendController(sendController); input.setMaxTextLength(MAX_BLOG_POST_TEXT_LENGTH); - input.setListener(this); progressBar = findViewById(R.id.progressBar); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java index 5d53b8d19d97791787ed6dea9baa090f6091ae78..167b7606a9f1ccb1c919480a94c35e5907bcfc3d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java @@ -63,9 +63,11 @@ import org.briarproject.briar.android.forum.ForumActivity; import org.briarproject.briar.android.introduction.IntroductionActivity; import org.briarproject.briar.android.privategroup.conversation.GroupActivity; import org.briarproject.briar.android.view.BriarRecyclerView; +import org.briarproject.briar.android.view.TextAttachmentController; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView.AttachImageListener; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.client.ProtocolStateException; @@ -166,6 +168,7 @@ public class ConversationActivity extends BriarActivity private BriarRecyclerView list; private LinearLayoutManager layoutManager; private TextInputView textInputView; + private TextSendController sendController; // Fields that are accessed from background threads must be volatile @Inject @@ -255,12 +258,15 @@ public class ConversationActivity extends BriarActivity list.setEmptyText(getString(R.string.no_private_messages)); textInputView = findViewById(R.id.text_input_container); - textInputView.setMaxTextLength(MAX_PRIVATE_MESSAGE_TEXT_LENGTH); - textInputView.setEnabled(false); - textInputView.setListener(this); if (FEATURE_FLAG_IMAGE_ATTACHMENTS) { - textInputView.setAttachImageListener(this, getWindowManager()); + sendController = new TextAttachmentController(textInputView, this, + this, getWindowManager()); + } else { + sendController = new TextSendController(textInputView, this, false); } + textInputView.setSendController(sendController); + textInputView.setMaxTextLength(MAX_PRIVATE_MESSAGE_TEXT_LENGTH); + textInputView.setEnabled(false); } @Override @@ -278,7 +284,8 @@ public class ConversationActivity extends BriarActivity snackbar.getView().setBackgroundResource(R.color.briar_primary); snackbar.show(); } else if (request == REQUEST_ATTACH_IMAGE && result == RESULT_OK) { - textInputView.onImageReceived(data); + // remove cast when removing FEATURE_FLAG_IMAGE_ATTACHMENTS + ((TextAttachmentController) sendController).onImageReceived(data); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java index 651a05413e23e01a93851cc29f55fdd8e9b676bb..1bfaff70eac31e0e8e8d60785817f02caff34dc6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java @@ -24,6 +24,7 @@ import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.api.introduction.IntroductionManager; import java.util.List; @@ -102,6 +103,9 @@ public class IntroductionMessageFragment extends BaseFragment View v = inflater.inflate(R.layout.introduction_message, container, false); ui = new ViewHolder(v); + TextSendController sendController = + new TextSendController(ui.message, this, true); + ui.message.setSendController(sendController); ui.message.setMaxTextLength(MAX_INTRODUCTION_TEXT_LENGTH); ui.message.setEnabled(false); @@ -162,9 +166,6 @@ public class IntroductionMessageFragment extends BaseFragment ui.progressBar.setVisibility(GONE); if (possible) { - // set button action - ui.message.setListener(IntroductionMessageFragment.this); - // show views ui.notPossible.setVisibility(GONE); ui.message.setVisibility(VISIBLE); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java index 7f732a7609b4f6b16851b11047db56b1706c3656..c05a0f357ea02c83006eb6d204c6b764eb3f936e 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java @@ -18,6 +18,7 @@ import org.briarproject.briar.R; import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.view.LargeTextInputView; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import java.util.List; @@ -44,10 +45,12 @@ public abstract class BaseMessageFragment extends BaseFragment View v = inflater.inflate(R.layout.fragment_message, container, false); message = v.findViewById(R.id.messageView); + TextSendController sendController = + new TextSendController(message, this, true); + message.setSendController(sendController); message.setMaxTextLength(listener.getMaximumTextLength()); message.setButtonText(getString(getButtonText())); message.setHint(getHintText()); - message.setListener(this); return v; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index 9429b0ed8628f64d19eac97c93aa303e19da9ad3..cc63423ab46a8ec8c1edb702b050ce08e1407bfd 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -29,6 +29,7 @@ import org.briarproject.briar.android.threaded.ThreadListController.ThreadListLi import org.briarproject.briar.android.view.BriarRecyclerView; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextInputView.SendListener; +import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.android.view.UnreadMessageButton; import org.briarproject.briar.api.client.NamedGroup; import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout; @@ -88,8 +89,10 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI getController().setGroupId(groupId); textInput = findViewById(R.id.text_input_container); + TextSendController sendController = + new TextSendController(textInput, this, false); + textInput.setSendController(sendController); textInput.setMaxTextLength(getMaxTextLength()); - textInput.setListener(this); list = findViewById(R.id.list); layoutManager = new LinearLayoutManager(this); // FIXME pre-fetching messes with read state, find better solution #1289 diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java index 1427f33efa3afd12ec6afb46a6d5955a50137191..87b9b9decb20cbbb685f62c843b7b7540e7711c8 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java @@ -71,7 +71,7 @@ public class LargeTextInputView extends TextInputView { } public void setButtonText(String text) { - ((Button) sendButton).setText(text); + ((Button) findViewById(R.id.btn_send)).setText(text); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java index 04571d012868982c44c54155d230643c2c04c43a..b61d76452ad0b5bad30eb1d9ab7ad0215e2b2f04 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextAttachmentController.java @@ -6,6 +6,7 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.design.widget.FloatingActionButton; @@ -13,7 +14,6 @@ import android.support.v4.view.AbsSavedState; import android.support.v7.graphics.Palette; import android.support.v7.widget.AppCompatImageButton; import android.util.DisplayMetrics; -import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; @@ -28,6 +28,7 @@ import com.bumptech.glide.request.target.Target; import org.briarproject.briar.R; import org.briarproject.briar.android.conversation.glide.GlideApp; import org.briarproject.briar.android.view.TextInputView.AttachImageListener; +import org.briarproject.briar.android.view.TextInputView.SendListener; import java.util.ArrayList; import java.util.List; @@ -53,21 +54,21 @@ import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; @UiThread -class TextAttachmentController extends TextSendController { +public class TextAttachmentController extends TextSendController { private final AppCompatImageButton imageButton; private final ViewGroup imageLayout; private final ImageView imageView; - @Nullable - private AttachImageListener imageListener; + private final AttachImageListener imageListener; private CharSequence textHint; private List<Uri> imageUris = emptyList(); - TextAttachmentController(View v, View sendButton, - TextInputController textInput) { - super(sendButton, textInput, true); + public TextAttachmentController(TextInputView v, SendListener listener, + AttachImageListener imageListener, WindowManager windowManager) { + super(v, listener, true); + this.imageListener = imageListener; imageLayout = v.findViewById(R.id.imageLayout); imageView = v.findViewById(R.id.imageView); @@ -82,11 +83,7 @@ class TextAttachmentController extends TextSendController { textInput.clearText(); reset(); }); - } - public void setAttachImageListener(AttachImageListener imageListener, - WindowManager windowManager) { - this.imageListener = imageListener; // set preview size based on screen height DisplayMetrics displayMetrics = new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(displayMetrics); @@ -98,20 +95,16 @@ class TextAttachmentController extends TextSendController { } @Override - public void onTextValidityChanged(boolean isEmpty) { + public void onTextIsEmptyChanged(boolean isEmpty) { if (imageUris.isEmpty()) showImageButton(isEmpty); } @Override void onSendButtonClicked() { - if (listener != null) { - if (textInput.isTooLong()) { - textInput.showError(); - return; - } + if (canSend()) { listener.onSendClick(textInput.getText(), imageUris); + reset(); } - reset(); } private void onImageButtonClicked() { @@ -124,7 +117,7 @@ class TextAttachmentController extends TextSendController { requireNonNull(imageListener).onAttachImage(intent); } - void onImageReceived(@Nullable Intent resultData) { + public void onImageReceived(@Nullable Intent resultData) { if (resultData == null) return; if (resultData.getData() != null) { imageUris = singletonList(resultData.getData()); @@ -205,7 +198,7 @@ class TextAttachmentController extends TextSendController { } else { sendButton.setVisibility(VISIBLE); // enable/disable buttons right away to allow fast sending - sendButton.setEnabled(true); + sendButton.setEnabled(enabled); imageButton.setEnabled(false); if (SDK_INT <= 15) { imageButton.setVisibility(INVISIBLE); @@ -231,6 +224,7 @@ class TextAttachmentController extends TextSendController { showImageButton(true); } + @Override public Parcelable onSaveInstanceState(@Nullable Parcelable superState) { SavedState state = new SavedState(superState == null ? EMPTY_STATE : superState); @@ -238,8 +232,9 @@ class TextAttachmentController extends TextSendController { return state; } + @Override @Nullable - public Parcelable onRestoreInstanceState(Parcelable inState) { + public Parcelable onRestoreInstanceState(@NonNull Parcelable inState) { SavedState state = (SavedState) inState; imageUris = state.imageUris; onNewUris(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputController.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputController.java index 991f37af1f654bca15e50b4facae76427f81c479..4b765c53d3eaa935646e77412de6b8ae41b81416 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputController.java @@ -6,7 +6,6 @@ import android.os.IBinder; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.annotation.UiThread; -import android.support.design.widget.Snackbar; import android.support.v7.widget.AppCompatImageButton; import android.text.Editable; import android.text.TextWatcher; @@ -21,9 +20,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; import static android.content.Context.INPUT_METHOD_SERVICE; -import static android.support.design.widget.Snackbar.LENGTH_SHORT; import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT; import static java.util.Objects.requireNonNull; +import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong; import static org.briarproject.briar.android.view.TextInputView.TextValidityListener; @UiThread @@ -35,7 +34,8 @@ class TextInputController implements TextWatcher { private final EmojiPopup emojiPopup; private final EmojiEditText editText; - private @Nullable TextValidityListener listener; + @Nullable + private TextValidityListener listener; private int maxLength = Integer.MAX_VALUE; private final boolean emptyTextAllowed; private boolean isEmpty = true; @@ -66,15 +66,16 @@ class TextInputController implements TextWatcher { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - if (emptyTextAllowed || listener == null) return; - if (s.toString().trim().length() == 0) { + // Need to start at position 0 to change empty + if (start != 0 || emptyTextAllowed || listener == null) return; + if (s.length() == 0) { if (!isEmpty) { isEmpty = true; - listener.onTextValidityChanged(true); + listener.onTextIsEmptyChanged(true); } } else if (isEmpty) { isEmpty = false; - listener.onTextValidityChanged(false); + listener.onTextIsEmptyChanged(false); } } @@ -86,9 +87,13 @@ class TextInputController implements TextWatcher { this.maxLength = maxLength; } + boolean isEmpty() { + return getText() == null; + } + boolean isTooLong() { return editText.getText() != null && - editText.getText().toString().trim().length() > maxLength; + utf8IsTooLong(editText.getText().toString().trim(), maxLength); } /** @@ -98,9 +103,9 @@ class TextInputController implements TextWatcher { @Nullable String getText() { Editable editable = editText.getText(); - if (editable == null || editable.toString().trim().length() == 0) - return null; - return editable.toString().trim(); + String str = editable == null ? null : editable.toString().trim(); + if (str == null || str.length() == 0) return null; + return str; } void clearText() { @@ -123,10 +128,6 @@ class TextInputController implements TextWatcher { this.listener = listener; } - void showError() { - Snackbar.make(editText, R.string.text_too_long, LENGTH_SHORT).show(); - } - boolean requestFocus(int direction, Rect previouslyFocusedRect) { return editText.requestFocus(direction, previouslyFocusedRect); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java index f57311d44d421888ed2d700f960b05935461c636..21e4c0950c0de6df7b66f5a484a962672c519e42 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java @@ -14,8 +14,6 @@ import android.support.annotation.UiThread; import android.support.v7.widget.AppCompatImageButton; import android.util.AttributeSet; import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; import com.vanniktech.emoji.EmojiEditText; import com.vanniktech.emoji.RecentEmoji; @@ -43,12 +41,9 @@ public class TextInputView extends KeyboardAwareLinearLayout { RecentEmoji recentEmoji; TextInputController textInputController; + @Nullable TextSendController textSendController; EmojiEditText editText; - View sendButton; - - @Nullable - TextAttachmentController attachmentController; public TextInputView(Context context) { this(context, null); @@ -87,8 +82,6 @@ public class TextInputView extends KeyboardAwareLinearLayout { String hint = attributes.getString(R.styleable.TextInputView_hint); boolean allowEmptyText = attributes .getBoolean(R.styleable.TextInputView_allowEmptyText, false); - boolean supportsAttachments = attributes - .getBoolean(R.styleable.TextInputView_supportsAttachments, false); attributes.recycle(); // set up input controller @@ -97,69 +90,55 @@ public class TextInputView extends KeyboardAwareLinearLayout { textInputController = new TextInputController(this, emojiToggle, editText, recentEmoji, allowEmptyText); if (hint != null) textInputController.setHint(hint); - - // set up sending controller - sendButton = findViewById(R.id.btn_send); - if (supportsAttachments) { - textSendController = new TextAttachmentController(this, sendButton, - textInputController); - } else { - textSendController = new TextSendController(sendButton, - textInputController, allowEmptyText); - } - textInputController.setTextValidityListener(textSendController); - - // support sending with Ctrl+Enter - editText.setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KEYCODE_ENTER && event.isCtrlPressed()) { - textSendController.onSendButtonClicked(); - return true; - } - return false; - }); } @Nullable @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); - if (attachmentController != null) { - superState = attachmentController.onSaveInstanceState(superState); + if (textSendController != null) { + superState = textSendController.onSaveInstanceState(superState); } return superState; } @Override protected void onRestoreInstanceState(Parcelable state) { - if (attachmentController != null) { + if (textSendController != null) { Parcelable outState = - attachmentController.onRestoreInstanceState(state); + textSendController.onRestoreInstanceState(state); super.onRestoreInstanceState(outState); } else { super.onRestoreInstanceState(state); } } - public void setListener(SendListener listener) { - textSendController.setSendListener(listener); - } + /** + * Call this in onCreate() before any other methods of this class. + */ + public <T extends TextSendController> void setSendController(T controller) { + textSendController = controller; + textInputController.setTextValidityListener(textSendController); - public void setAttachImageListener(AttachImageListener imageListener, - WindowManager windowManager) { - attachmentController = (TextAttachmentController) textSendController; - attachmentController.setAttachImageListener(imageListener, windowManager); + // support sending with Ctrl+Enter + editText.setOnKeyListener((v, keyCode, event) -> { + if (keyCode == KEYCODE_ENTER && event.isCtrlPressed()) { + textSendController.onSendButtonClicked(); + return true; + } + return false; + }); } - public void onImageReceived(@Nullable Intent resultData) { - if (attachmentController == null) throw new IllegalStateException(); - attachmentController.onImageReceived(resultData); + public TextInputController getTextInputController() { + return textInputController; } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); textInputController.setEnabled(enabled); - textSendController.setEnabled(enabled); + requireNonNull(textSendController).setEnabled(enabled); } @Override @@ -195,7 +174,7 @@ public class TextInputView extends KeyboardAwareLinearLayout { } interface TextValidityListener { - void onTextValidityChanged(boolean isEmpty); + void onTextIsEmptyChanged(boolean isEmpty); } public interface AttachImageListener { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextSendController.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextSendController.java index 3d0cb30c1f73f81535030f1efac80d185db3baa8..fc04484a7c62eefe2e1974bbd869bf9203d18b94 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextSendController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextSendController.java @@ -1,62 +1,77 @@ package org.briarproject.briar.android.view; +import android.os.Parcelable; +import android.support.annotation.CallSuper; import android.support.annotation.Nullable; import android.support.annotation.UiThread; +import android.support.design.widget.Snackbar; import android.view.View; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.R; import org.briarproject.briar.android.view.TextInputView.SendListener; import org.briarproject.briar.android.view.TextInputView.TextValidityListener; +import static android.support.design.widget.Snackbar.LENGTH_SHORT; import static java.util.Collections.emptyList; @UiThread @NotNullByDefault -class TextSendController implements TextValidityListener { +public class TextSendController implements TextValidityListener { protected final TextInputController textInput; protected final View sendButton; - @Nullable - protected SendListener listener; + protected final SendListener listener; protected boolean enabled = true; private final boolean allowEmptyText; private boolean wasEmpty = true; - TextSendController(View sendButton, TextInputController textInput, + public TextSendController(TextInputView v, SendListener listener, boolean allowEmptyText) { - this.sendButton = sendButton; - this.sendButton.setOnClickListener(v -> onSendButtonClicked()); + this.sendButton = v.findViewById(R.id.btn_send); + this.sendButton.setOnClickListener(view -> onSendButtonClicked()); this.sendButton.setEnabled(allowEmptyText); - this.textInput = textInput; + this.listener = listener; + this.textInput = v.getTextInputController(); this.allowEmptyText = allowEmptyText; } @Override - public void onTextValidityChanged(boolean isEmpty) { + public void onTextIsEmptyChanged(boolean isEmpty) { sendButton.setEnabled(enabled && !isEmpty); wasEmpty = isEmpty; } - public void setEnabled(boolean enabled) { - sendButton.setOnClickListener( - enabled ? v -> onSendButtonClicked() : null); - sendButton.setEnabled(!wasEmpty || allowEmptyText); - this.enabled = enabled; + @Nullable + public Parcelable onSaveInstanceState(@Nullable Parcelable superState) { + return superState; } - void setSendListener(SendListener listener) { - this.listener = listener; + @Nullable + public Parcelable onRestoreInstanceState(Parcelable state) { + return state; + } + + @CallSuper + public void setEnabled(boolean enabled) { + sendButton.setEnabled(enabled && (!wasEmpty || allowEmptyText)); + this.enabled = enabled; } void onSendButtonClicked() { - if (listener != null) { - if (textInput.isTooLong()) { - textInput.showError(); - return; - } + if (canSend()) { listener.onSendClick(textInput.getText(), emptyList()); } } + protected boolean canSend() { + if (textInput.isTooLong()) { + Snackbar.make(sendButton, R.string.text_too_long, LENGTH_SHORT) + .show(); + return false; + } + return enabled && (allowEmptyText || !textInput.isEmpty()); + } + } diff --git a/briar-android/src/main/res/layout/activity_conversation.xml b/briar-android/src/main/res/layout/activity_conversation.xml index 4ae3cedab90112a7cf34ce7c6cb15e996b4bc050..a3afa6b6d70fa03ac0a829bcc2d01b4e21239977 100644 --- a/briar-android/src/main/res/layout/activity_conversation.xml +++ b/briar-android/src/main/res/layout/activity_conversation.xml @@ -54,7 +54,6 @@ android:id="@+id/text_input_container" android:layout_width="match_parent" android:layout_height="wrap_content" - app:hint="@string/message_hint" - app:supportsAttachments="true"/> + app:hint="@string/message_hint"/> </LinearLayout> \ No newline at end of file diff --git a/briar-android/src/main/res/values/attrs.xml b/briar-android/src/main/res/values/attrs.xml index a97af7189acd3858f8507554ad5c804a39e36527..eab6a660a1c6de2e56245e1237a107b11ba4bfd7 100644 --- a/briar-android/src/main/res/values/attrs.xml +++ b/briar-android/src/main/res/values/attrs.xml @@ -22,7 +22,6 @@ <declare-styleable name="TextInputView"> <attr name="hint" format="string"/> <attr name="allowEmptyText" format="boolean"/> - <attr name="supportsAttachments" format="boolean"/> </declare-styleable> <declare-styleable name="LargeTextInputView">