Browse Source

implement editor view for replies

pull/45/head
Thodoris1999 6 years ago
parent
commit
9d1985c2de
  1. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/TestEditView.java
  2. 29
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  3. 34
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  4. 19
      app/src/main/java/gr/thmmy/mthmmy/utils/EditorView.java
  5. 9
      app/src/main/java/gr/thmmy/mthmmy/utils/EmojiKeyboard.java
  6. 6
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
  7. 97
      app/src/main/res/layout/activity_topic.xml
  8. 34
      app/src/main/res/layout/activity_topic_quick_reply_row.xml

14
app/src/main/java/gr/thmmy/mthmmy/activities/TestEditView.java

@ -22,7 +22,7 @@ public class TestEditView extends AppCompatActivity implements EmojiKeyboard.Emo
emojiKeyboard = findViewById(R.id.emoji_keyboard);
InputConnection ic = editorView.getInputConnection();
emojiKeyboard.setInputConnection(ic);
setEmojiKeyboardInputConnection(ic);
editorView.setEmojiKeyboardOwner(this);
}
@ -31,11 +31,21 @@ public class TestEditView extends AppCompatActivity implements EmojiKeyboard.Emo
emojiKeyboard.setVisibility(visible ? View.VISIBLE : View.GONE);
}
@Override
public boolean isEmojiKeyboardVisible() {
return emojiKeyboard.getVisibility() == View.VISIBLE;
}
@Override
public void setEmojiKeyboardInputConnection(InputConnection ic) {
emojiKeyboard.setInputConnection(ic);
}
@Override
public void onBackPressed() {
if (emojiKeyboard.getVisibility() == View.VISIBLE) {
emojiKeyboard.setVisibility(View.GONE);
editorView.notifyKeyboardVisibility(false);
editorView.setEmojiKeyboardVisible(false);
} else {
super.onBackPressed();
}

29
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -23,6 +23,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
@ -44,6 +45,7 @@ import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.CustomLinearLayoutManager;
import gr.thmmy.mthmmy.utils.EmojiKeyboard;
import gr.thmmy.mthmmy.utils.HTMLUtils;
import gr.thmmy.mthmmy.utils.parsing.ParseHelpers;
import gr.thmmy.mthmmy.viewmodel.TopicViewModel;
@ -59,7 +61,8 @@ import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
* key {@link #BUNDLE_TOPIC_TITLE} for faster title rendering.
*/
@SuppressWarnings("unchecked")
public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFocusChangeListener {
public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFocusChangeListener,
EmojiKeyboard.EmojiKeyboardOwner{
//Activity's variables
/**
* The key to use when putting topic's url String to {@link TopicActivity}'s Bundle.
@ -112,6 +115,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
private ImageButton lastPage;
private Snackbar snackbar;
private TopicViewModel viewModel;
private EmojiKeyboard emojiKeyboard;
//Fix for vector drawables on android <21
static {
@ -159,6 +163,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
createDrawer();
progressBar = findViewById(R.id.progressBar);
emojiKeyboard = findViewById(R.id.emoji_keyboard);
postsList = new ArrayList<>();
@ -254,6 +259,13 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (drawer.isDrawerOpen()) {
drawer.closeDrawer();
return;
} else if (emojiKeyboard.getVisibility() == View.VISIBLE) {
emojiKeyboard.setVisibility(View.GONE);
if (viewModel.isEditingPost())
topicAdapter.notifyItemChanged(viewModel.getPostBeingEditedPosition());
if (viewModel.isWritingReply())
topicAdapter.notifyItemChanged(viewModel.postCount() - 1);
return;
} else if (viewModel.isWritingReply()) {
postsList.remove(postsList.size() - 1);
topicAdapter.notifyItemRemoved(postsList.size());
@ -293,6 +305,21 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
recyclerView.scrollToPosition(position);
}
@Override
public void setEmojiKeyboardVisible(boolean visible) {
emojiKeyboard.setVisibility(visible ? View.VISIBLE : View.GONE);
}
@Override
public boolean isEmojiKeyboardVisible() {
return emojiKeyboard.getVisibility() == View.VISIBLE;
}
@Override
public void setEmojiKeyboardInputConnection(InputConnection ic) {
emojiKeyboard.setInputConnection(ic);
}
//--------------------------------------BOTTOM NAV BAR METHODS----------------------------------
/**

34
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java

@ -21,6 +21,7 @@ import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
@ -46,6 +47,8 @@ import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyFile;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.CircleTransform;
import gr.thmmy.mthmmy.utils.EditorView;
import gr.thmmy.mthmmy.utils.EmojiKeyboard;
import gr.thmmy.mthmmy.utils.parsing.ParseHelpers;
import gr.thmmy.mthmmy.viewmodel.TopicViewModel;
import timber.log.Timber;
@ -71,6 +74,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static int THUMBNAIL_SIZE;
private final Context context;
private final OnPostFocusChangeListener postFocusListener;
private final EmojiKeyboard.EmojiKeyboardOwner emojiKeyboardOwner;
private final List<Post> postsList;
private TopicViewModel viewModel;
@ -82,6 +86,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
this.context = context;
this.postsList = postsList;
this.postFocusListener = context;
this.emojiKeyboardOwner = context;
viewModel = ViewModelProviders.of(context).get(TopicViewModel.class);
@ -103,9 +108,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} else if (viewType == Post.TYPE_QUICK_REPLY) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_topic_quick_reply_row, parent, false);
view.findViewById(R.id.quick_reply_submit).setEnabled(true);
final EditText quickReplyText = view.findViewById(R.id.quick_reply_text);
final EditText quickReplyText = ((EditorView) view.findViewById(R.id.reply_editorview)).getEditText();
quickReplyText.setFocusableInTouchMode(true);
quickReplyText.setOnFocusChangeListener((v, hasFocus) -> quickReplyText.post(() -> {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
@ -455,24 +459,31 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.username.setText(getSessionManager().getUsername());
holder.quickReplySubject.setText("Re: " + viewModel.getTopicTitle().getValue());
holder.quickReply.setText(viewModel.getBuildedQuotes());
holder.replyEditor.setEmojiKeyboardOwner(emojiKeyboardOwner);
InputConnection ic = holder.replyEditor.getInputConnection();
emojiKeyboardOwner.setEmojiKeyboardInputConnection(ic);
holder.replyEditor.setEmojiKeyboardVisible(emojiKeyboardOwner.isEmojiKeyboardVisible());
holder.submitButton.setOnClickListener(view -> {
holder.replyEditor.setText(viewModel.getBuildedQuotes());
holder.replyEditor.setOnSubmitListener(view -> {
if (holder.quickReplySubject.getText().toString().isEmpty()) return;
if (holder.quickReply.getText().toString().isEmpty()) return;
if (holder.replyEditor.getText().toString().isEmpty()) {
holder.replyEditor.setError("Required");
return;
}
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
holder.itemView.setAlpha(0.5f);
holder.itemView.setEnabled(false);
viewModel.postReply(context, holder.quickReplySubject.getText().toString(),
holder.quickReply.getText().toString());
holder.replyEditor.getText().toString());
});
holder.replyEditor.setOnClickListener(view -> holder.replyEditor.setError(null));
if (backPressHidden) {
holder.quickReply.requestFocus();
holder.replyEditor.requestFocus();
backPressHidden = false;
}
} else if (currentHolder instanceof EditMessageViewHolder) {
@ -575,16 +586,15 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class QuickReplyViewHolder extends RecyclerView.ViewHolder {
final ImageView thumbnail;
final TextView username;
final EditText quickReply, quickReplySubject;
final AppCompatImageButton submitButton;
final EditText quickReplySubject;
final EditorView replyEditor;
QuickReplyViewHolder(View quickReply) {
super(quickReply);
thumbnail = quickReply.findViewById(R.id.thumbnail);
username = quickReply.findViewById(R.id.username);
this.quickReply = quickReply.findViewById(R.id.quick_reply_text);
quickReplySubject = quickReply.findViewById(R.id.quick_reply_subject);
submitButton = quickReply.findViewById(R.id.quick_reply_submit);
replyEditor = quickReply.findViewById(R.id.reply_editorview);
}
}

19
app/src/main/java/gr/thmmy/mthmmy/utils/EditorView.java

@ -4,6 +4,7 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
@ -230,10 +231,18 @@ public class EditorView extends LinearLayout {
});
}
public TextInputEditText getEditText() {
return editText;
}
public Editable getText() {
return editText.getText();
}
public void setText(Editable text) {
editText.setText(text);
}
public void setText(CharSequence text) {
editText.setText(text);
}
@ -254,13 +263,11 @@ public class EditorView extends LinearLayout {
return editText.onCreateInputConnection(new EditorInfo());
}
public void notifyKeyboardVisibility(boolean visible) {
if (visible) {
public void setEmojiKeyboardVisible(boolean visible) {
if (visible)
emojiButton.setImageResource(R.drawable.ic_keyboard_grey_24dp);
emojiKeyboardVisible = true;
} else {
else
emojiButton.setImageResource(R.drawable.ic_tag_faces_grey_24dp);
emojiKeyboardVisible = false;
}
emojiKeyboardVisible = visible;
}
}

9
app/src/main/java/gr/thmmy/mthmmy/utils/EmojiKeyboard.java

@ -3,9 +3,11 @@ package gr.thmmy.mthmmy.utils;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -155,6 +157,7 @@ public class EmojiKeyboard extends LinearLayout {
public void init(Context context, AttributeSet attrs) {
LayoutInflater.from(context).inflate(R.layout.emoji_keyboard, this, true);
setOrientation(VERTICAL);
RecyclerView emojiRecyclerview = findViewById(R.id.emoji_recyclerview);
emojiRecyclerview.setHasFixedSize(true);
@ -163,11 +166,11 @@ public class EmojiKeyboard extends LinearLayout {
emojiRecyclerview.setLayoutManager(emojiLayoutManager);
EmojiKeyboardAdapter emojiKeyboardAdapter = new EmojiKeyboardAdapter(emojis);
emojiKeyboardAdapter.setOnEmojiClickListener(((view, position) -> {
emojiKeyboardAdapter.setOnEmojiClickListener((view, position) -> {
if (inputConnection == null) return;
String bbcode = emojis[position].getBbcode();
inputConnection.commitText(bbcode, 1);
}));
});
emojiRecyclerview.setAdapter(emojiKeyboardAdapter);
AppCompatImageButton backspaceButton = findViewById(R.id.backspace_button);
// backspace behavior
@ -203,6 +206,8 @@ public class EmojiKeyboard extends LinearLayout {
public interface EmojiKeyboardOwner {
void setEmojiKeyboardVisible(boolean visible);
boolean isEmojiKeyboardVisible();
void setEmojiKeyboardInputConnection(InputConnection ic);
}
class Emoji {

6
app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java

@ -375,4 +375,10 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
throw new NullPointerException("Reply preparation was not found");
return prepareForReplyResult.getValue().getBuildedQuotes();
}
public int postCount() {
if (postsList.getValue() == null)
throw new NullPointerException("No page has been loaded yet!");
return postsList.getValue().size();
}
}

97
app/src/main/res/layout/activity_topic.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.design.widget.CoordinatorLayout 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/main_content"
@ -9,52 +8,64 @@
android:fitsSystemWindows="true"
tools:context=".activities.topic.TopicActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/ToolbarTheme">
android:layout_height="match_parent" >
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStartWithNavigation="0dp"
app:popupTheme="@style/ToolbarTheme">
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/ToolbarTheme">
<TextView
android:id="@+id/toolbar_title"
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/topic_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|start"
android:background="@color/background"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:clipToPadding="false"
android:scrollbars="none"
tools:context="gr.thmmy.mthmmy.activities.topic.TopicActivity"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView>
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStartWithNavigation="0dp"
app:popupTheme="@style/ToolbarTheme">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/topic_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top|start"
android:layout_below="@id/appbar"
android:layout_above="@id/emoji_keyboard"
android:background="@color/background"
android:clipToPadding="false"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="gr.thmmy.mthmmy.activities.topic.TopicActivity" />
<gr.thmmy.mthmmy.utils.EmojiKeyboard
android:id="@+id/emoji_keyboard"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_alignParentBottom="true"
android:visibility="gone"/>
</RelativeLayout>
<TextView
android:id="@+id/error_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/network_error_retry_prompt"
android:textSize="32sp"
android:textColor="@color/white"
android:gravity="center"
android:textSize="32sp"
android:visibility="gone" />
<LinearLayout
@ -73,7 +84,7 @@
android:layout_weight="0.8"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/button_first"
app:srcCompat="@drawable/page_first"/>
app:srcCompat="@drawable/page_first" />
<ImageButton
android:id="@+id/page_previous_button"
@ -82,7 +93,7 @@
android:layout_weight="0.8"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/button_previous"
app:srcCompat="@drawable/page_previous"/>
app:srcCompat="@drawable/page_previous" />
<TextView
android:id="@+id/page_indicator"
@ -94,7 +105,7 @@
android:hint="@string/button_page"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="22sp"/>
android:textSize="22sp" />
<ImageButton
android:id="@+id/page_next_button"
@ -103,7 +114,7 @@
android:layout_weight="0.8"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/button_next"
app:srcCompat="@drawable/page_next"/>
app:srcCompat="@drawable/page_next" />
<ImageButton
android:id="@+id/page_last_button"
@ -112,7 +123,7 @@
android:layout_weight="0.8"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/button_last"
app:srcCompat="@drawable/page_last"/>
app:srcCompat="@drawable/page_last" />
</LinearLayout>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
@ -125,7 +136,7 @@
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|center"
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal"/>
app:mpb_progressStyle="horizontal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/topic_fab"
@ -135,7 +146,7 @@
android:layout_marginBottom="50dp"
android:layout_marginEnd="@dimen/fab_margins"
app:layout_behavior="gr.thmmy.mthmmy.utils.ScrollAwareFABBehavior"
app:srcCompat="@drawable/ic_reply"/>
app:srcCompat="@drawable/ic_reply" />
</android.support.design.widget.CoordinatorLayout>

34
app/src/main/res/layout/activity_topic_quick_reply_row.xml

@ -80,39 +80,11 @@
android:textSize="10sp"
tools:ignore="SmallSp" />
</RelativeLayout>
<LinearLayout
<gr.thmmy.mthmmy.utils.EditorView
android:id="@+id/reply_editorview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<android.support.design.widget.TextInputLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<EditText
android:id="@+id/quick_reply_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/quick_reply"
android:inputType="textMultiLine" />
</android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/quick_reply_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="5dp"
android:layout_marginEnd="5dp"
android:background="@color/card_background"
android:contentDescription="@string/submit"
app:srcCompat="@drawable/ic_send_accent_24dp" />
</LinearLayout>
card_view:hint="Post message"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
Loading…
Cancel
Save