diff --git a/app/build.gradle b/app/build.gradle index dbebe49..c6d3a22 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,5 +127,6 @@ dependencies { implementation 'com.github.mancj:MaterialSearchBar:0.8.5' implementation "io.github.kobakei:ratethisapp:1.2.0" + implementation 'com.github.HITGIF:TextFieldBoxes:1.4.5' } \ No newline at end of file diff --git a/app/src/acad/res/values/strings.xml b/app/src/acad/res/values/strings.xml index 418da0b..25a0239 100644 --- a/app/src/acad/res/values/strings.xml +++ b/app/src/acad/res/values/strings.xml @@ -187,6 +187,8 @@ RĂ©pondre publiquement Envoyer un commentaire Tout + + RĂ©pondre Listes de lecture Nom d\'affichage diff --git a/app/src/fdroid_full/play/release-notes/en-US/default.txt b/app/src/fdroid_full/play/release-notes/en-US/default.txt index 5100bd0..9b568e2 100644 --- a/app/src/fdroid_full/play/release-notes/en-US/default.txt +++ b/app/src/fdroid_full/play/release-notes/en-US/default.txt @@ -1,7 +1,5 @@ -- Theme: Light, Dark and auto -- Remove all comments of an account on your videos -- Sepia search: Allow interactions when the video is federated -- Mute accounts from comments -- Links clickable in video descriptions -- Fix all comments not displayed -- Fix some minor other bugs \ No newline at end of file +- Custom default instance depending of the country +- New comment feature +- See replies to comments +- Reply to comment +- Fix some issues when posting \ No newline at end of file diff --git a/app/src/full/res/values/strings.xml b/app/src/full/res/values/strings.xml index 2f4a97a..943e12a 100644 --- a/app/src/full/res/values/strings.xml +++ b/app/src/full/res/values/strings.xml @@ -13,7 +13,7 @@ %d reply %d replies - + Reply Theme Allow to change app theme The video cannot be federated! diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java index 5f71764..46522e0 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java @@ -35,7 +35,6 @@ import android.text.Html; import android.text.Spanned; import android.view.LayoutInflater; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -150,10 +149,11 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd private boolean flag_loading; private boolean isMyVideo; private List comments; - private CommentListAdapter commentListAdapter, commentReplyListAdapter; + private CommentListAdapter commentListAdapter; + private CommentListAdapter commentReplyListAdapter; private boolean sepiaSearch; private ActivityPeertubeBinding binding; - + private List commentsThread; public static void hideKeyboard(Activity activity) { if (activity != null && activity.getWindow() != null) { activity.getWindow().getDecorView(); @@ -340,15 +340,15 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd return; } List commentThreadDataList = apiResponse.getCommentThreadData().getChildren(); - List comments = generateCommentReply(commentThreadDataList, new ArrayList<>()); - if (comments.size() > 0) { - commentReplyListAdapter = new CommentListAdapter(comments, Helper.isVideoOwner(PeertubeActivity.this, peertube)); + commentsThread = generateCommentReply(commentThreadDataList, new ArrayList<>()); + if (commentsThread.size() > 0) { + commentReplyListAdapter = new CommentListAdapter(commentsThread, Helper.isVideoOwner(PeertubeActivity.this, peertube)); LinearLayoutManager mLayoutManager = new LinearLayoutManager(PeertubeActivity.this); binding.peertubeReply.setLayoutManager(mLayoutManager); binding.peertubeReply.setNestedScrollingEnabled(false); binding.peertubeReply.setAdapter(commentReplyListAdapter); binding.peertubeReply.setVisibility(View.VISIBLE); - commentReplyListAdapter.notifyItemRangeInserted(0, comments.size()); + commentReplyListAdapter.notifyItemRangeInserted(0, commentsThread.size()); } } @@ -412,28 +412,6 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd } } - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - View v = getCurrentFocus(); - - if ((ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && - v instanceof EditText && - v.getId() == R.id.add_comment_write) { - int[] scrcoords = new int[2]; - v.getLocationOnScreen(scrcoords); - float x = ev.getRawX() + v.getLeft() - scrcoords[0]; - float y = ev.getRawY() + v.getTop() - scrcoords[1]; - - if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom()) { - binding.addCommentRead.setVisibility(View.VISIBLE); - binding.addCommentWrite.setVisibility(View.GONE); - binding.send.setVisibility(View.GONE); - hideKeyboard(PeertubeActivity.this); - } - } - return super.dispatchTouchEvent(ev); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -466,7 +444,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd videoReport.setId(peertube.getId()); report.setVideo(videoReport); report.setReason(report_content.getText().toString()); - viewModel.report(report).observe(PeertubeActivity.this, apiResponse -> manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_VIDEO, apiResponse)); + viewModel.report(report).observe(PeertubeActivity.this, apiResponse -> manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_VIDEO,0, apiResponse)); alertDialog.dismiss(); dialog.dismiss(); } else if (type == RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT) { @@ -475,7 +453,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd accountReport.setId(peertube.getAccount().getId()); report.setAccount(accountReport); report.setReason(report_content.getText().toString()); - viewModel.report(report).observe(PeertubeActivity.this, apiResponse -> manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT, apiResponse)); + viewModel.report(report).observe(PeertubeActivity.this, apiResponse -> manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT, 0,apiResponse)); alertDialog.dismiss(); dialog.dismiss(); } @@ -526,49 +504,18 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd PlaylistsVM viewModel = new ViewModelProvider(this).get(PlaylistsVM.class); viewModel.videoExists(videoIds).observe(this, this::manageVIewPlaylist); + if( !Helper.isLoggedIn(PeertubeActivity.this)) { + binding.writeCommentContainer.setVisibility(View.GONE); + binding.writeCommentContainerReply.setVisibility(View.GONE); + } - binding.writeCommentContainer.setOnClickListener(v -> { - if (isLoggedIn(PeertubeActivity.this) && !sepiaSearch) { - binding.addCommentRead.setVisibility(View.GONE); - binding.addCommentWrite.setVisibility(View.VISIBLE); - binding.send.setVisibility(View.VISIBLE); - binding.addCommentWrite.requestFocus(); - binding.addCommentWrite.setSelection( binding.addCommentWrite.getText().length()); - } else { - if( sepiaSearch) { - Toasty.info(PeertubeActivity.this, getString(R.string.federation_issue), Toasty.LENGTH_SHORT).show(); - }else { - Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show(); - } - } - - }); - binding.writeCommentContainerReply.setOnClickListener(v -> { - if (isLoggedIn(PeertubeActivity.this) && !sepiaSearch) { - binding.addCommentReadReply.setVisibility(View.GONE); - binding.addCommentWriteReply.setVisibility(View.VISIBLE); - binding.send.setVisibility(View.VISIBLE); - binding.addCommentWriteReply.requestFocus(); - binding.addCommentWriteReply.setSelection( binding.addCommentWriteReply.getText().length()); - } else { - if( sepiaSearch) { - Toasty.info(PeertubeActivity.this, getString(R.string.federation_issue), Toasty.LENGTH_SHORT).show(); - }else { - Toasty.error(PeertubeActivity.this, getString(R.string.not_logged_in), Toast.LENGTH_SHORT).show(); - } - } - }); binding.send.setOnClickListener(v -> { if (isLoggedIn(PeertubeActivity.this) && !sepiaSearch) { String comment = binding.addCommentWrite.getText().toString(); if (comment.trim().length() > 0) { PostActionsVM viewModelComment = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModelComment.comment(ADD_COMMENT, peertube.getId(), null, comment).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(ADD_COMMENT, apiResponse1)); + viewModelComment.comment(ADD_COMMENT, peertube.getId(), null, comment).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(ADD_COMMENT, 0, apiResponse1)); binding.addCommentWrite.setText(""); - binding.addCommentRead.setVisibility(View.VISIBLE); - binding.addCommentWrite.setVisibility(View.GONE); - binding.sendReply.setVisibility(View.GONE); - binding.addCommentRead.requestFocus(); } } else { if( sepiaSearch) { @@ -615,7 +562,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd if (isLoggedIn(PeertubeActivity.this) && !sepiaSearch) { String newState = peertube.getMyRating().equals("like") ? "none" : "like"; PostActionsVM viewModelLike = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModelLike.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO, apiResponse1)); + viewModelLike.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO, 0, apiResponse1)); peertube.setMyRating(newState); int count = Integer.parseInt(binding.peertubeLikeCount.getText().toString()); if (newState.compareTo("none") == 0) { @@ -640,7 +587,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd if (isLoggedIn(PeertubeActivity.this) && !sepiaSearch) { String newState = peertube.getMyRating().equals("dislike") ? "none" : "dislike"; PostActionsVM viewModelLike = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModelLike.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO, apiResponse1)); + viewModelLike.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO,0, apiResponse1)); peertube.setMyRating(newState); int count = Integer.parseInt(binding.peertubeDislikeCount.getText().toString()); if (newState.compareTo("none") == 0) { @@ -913,10 +860,14 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd @Override public void onBackPressed() { - if (playInMinimized && player != null) { - enterVideoMode(); - } else { - super.onBackPressed(); + if( binding.writeCommentContainerReply.getVisibility() == View.VISIBLE) { + closeCommentThread(); + }else { + if (playInMinimized && player != null) { + enterVideoMode(); + } else { + super.onBackPressed(); + } } } @@ -999,20 +950,7 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd builderSingle.show(); } - @SuppressWarnings({"unused", "RedundantSuppression"}) - public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, APIResponse apiResponse) { - if (peertube.isCommentsEnabled() && statusAction == ADD_COMMENT) { - if( apiResponse.getComments() != null && apiResponse.getComments().size() > 0 ) { - comments.add(0, apiResponse.getComments().get(0)); - commentListAdapter.notifyItemInserted(0); - } - } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT) { - Toasty.success(PeertubeActivity.this, getString(R.string.successful_report), Toasty.LENGTH_LONG).show(); - } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_VIDEO) { - Toasty.success(PeertubeActivity.this, getString(R.string.successful_video_report), Toasty.LENGTH_LONG).show(); - } - } private void initFullscreenDialog() { @@ -1036,7 +974,8 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd fullScreenDialog.show(); } - public void openCommentThread(Comment comment){ + public void openCommentThread(Comment comment, int position){ + CommentVM commentViewModel = new ViewModelProvider(PeertubeActivity.this).get(CommentVM.class); binding.peertubeReply.setVisibility(View.GONE); @@ -1077,12 +1016,8 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd String commentView = binding.addCommentWriteReply.getText().toString(); if (commentView.trim().length() > 0) { PostActionsVM viewModelComment = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModelComment.comment(REPLY, peertube.getId(), comment.getId(), commentView).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(ADD_COMMENT, apiResponse1)); + viewModelComment.comment(REPLY, peertube.getId(), comment.getId(), commentView).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(REPLY, position, apiResponse1)); binding.addCommentWriteReply.setText(""); - binding.addCommentReadReply.setVisibility(View.VISIBLE); - binding.addCommentWriteReply.setVisibility(View.GONE); - binding.sendReply.setVisibility(View.GONE); - binding.addCommentReadReply.requestFocus(); } } else { if( sepiaSearch) { @@ -1115,6 +1050,26 @@ public class PeertubeActivity extends AppCompatActivity implements CommentListAd binding.replyThread.startAnimation(animate); } + @SuppressWarnings({"unused", "RedundantSuppression"}) + public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, int position, APIResponse apiResponse) { + + if (peertube.isCommentsEnabled() && statusAction == ADD_COMMENT) { + if( apiResponse.getComments() != null && apiResponse.getComments().size() > 0 ) { + comments.add(0, apiResponse.getComments().get(0)); + commentListAdapter.notifyItemInserted(0); + } + } else if (peertube.isCommentsEnabled() && statusAction == REPLY) { + if( apiResponse.getComments() != null && apiResponse.getComments().size() > 0 ) { + commentsThread.add(position, apiResponse.getComments().get(0)); + commentReplyListAdapter.notifyItemInserted(position); + } + } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT) { + Toasty.success(PeertubeActivity.this, getString(R.string.successful_report), Toasty.LENGTH_LONG).show(); + } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_VIDEO) { + Toasty.success(PeertubeActivity.this, getString(R.string.successful_video_report), Toasty.LENGTH_LONG).show(); + } + } + private void closeFullscreenDialog() { ((ViewGroup) binding.mediaVideo.getParent()).removeView(binding.mediaVideo); diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/data/CommentData.java b/app/src/main/java/app/fedilab/fedilabtube/client/data/CommentData.java index 62356a6..ca3e929 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/client/data/CommentData.java +++ b/app/src/main/java/app/fedilab/fedilabtube/client/data/CommentData.java @@ -57,6 +57,7 @@ public class CommentData { @SerializedName("videoId") private String videoId; private boolean isReply = false; + private boolean isReplyViewOpen = false; public AccountData.Account getAccount() { @@ -170,6 +171,14 @@ public class CommentData { public void setReply(boolean reply) { isReply = reply; } + + public boolean isReplyViewOpen() { + return isReplyViewOpen; + } + + public void setReplyViewOpen(boolean replyViewOpen) { + isReplyViewOpen = replyViewOpen; + } } diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java index 9df2196..1187d50 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/CommentListAdapter.java @@ -39,6 +39,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.widget.PopupMenu; +import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; @@ -59,8 +60,11 @@ import app.fedilab.fedilabtube.helper.EmojiHelper; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import es.dmoral.toasty.Toasty; +import studio.carbonylgroup.textfieldboxes.ExtendedEditText; import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPLY; +import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn; public class CommentListAdapter extends RecyclerView.Adapter { @@ -111,7 +115,7 @@ public class CommentListAdapter extends RecyclerView.Adapter { PopupMenu popup = new PopupMenu(context, holder.more_actions); @@ -161,7 +165,7 @@ public class CommentListAdapter extends RecyclerView.Adapter manageVIewPostActions(MUTE, apiResponse)); + viewModel.post(MUTE, comment.getAccount().getAcct(), null).observe((LifecycleOwner) context, apiResponse -> manageVIewPostActions(MUTE, 0, apiResponse)); comments.remove(comment); notifyDataSetChanged(); if (comments.size() == 0) { @@ -218,8 +222,8 @@ public class CommentListAdapter extends RecyclerView.Adapter ((PeertubeActivity) context).openCommentThread(comment)); - holder.comment_content.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment)); + holder.main_container.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment, i)); + holder.comment_content.setOnClickListener(v -> ((PeertubeActivity) context).openCommentThread(comment, i)); } if( comment.getTotalReplies() > 0) { holder.number_of_replies.setVisibility(View.VISIBLE); @@ -248,9 +252,38 @@ public class CommentListAdapter extends RecyclerView.Adapter{ + comment.setReplyViewOpen(!comment.isReplyViewOpen()); + notifyItemChanged(i); + }); + + holder.send_reply.setOnClickListener(null); + holder.send_reply.setOnClickListener(v -> { + if (isLoggedIn(context)) { + String commentView = holder.add_comment_write_reply.getText().toString(); + if (commentView.trim().length() > 0) { + PostActionsVM viewModelComment = new ViewModelProvider((ViewModelStoreOwner) context).get(PostActionsVM.class); + viewModelComment.comment(REPLY, comment.getVideoId(), comment.getId(), commentView).observe((LifecycleOwner) context, apiResponse1 -> manageVIewPostActions(REPLY, (int)holder.main_container.getTag(), apiResponse1)); + holder.add_comment_write_reply.setText(""); + comment.setReplyViewOpen(false); + notifyItemChanged(i); + } + } + }); } - public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, APIResponse apiResponse) { + public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, int i, APIResponse apiResponse) { if (apiResponse.getError() != null) { Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); @@ -266,7 +299,12 @@ public class CommentListAdapter extends RecyclerView.Adapter 0 ) { + comments.add(i+1, apiResponse.getComments().get(0)); + notifyItemInserted(i+1); + } + }else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_COMMENT) { Toasty.success(context, context.getString(R.string.successful_report_comment), Toasty.LENGTH_LONG).show(); }else if (statusAction == MUTE) { Toasty.info(context, context.getString(R.string.muted_done), Toast.LENGTH_LONG).show(); @@ -291,7 +329,7 @@ public class CommentListAdapter extends RecyclerView.Adapter manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_COMMENT, apiResponse)); + viewModel.report(report).observe((LifecycleOwner) context, apiResponse -> manageVIewPostActions(RetrofitPeertubeAPI.ActionType.REPORT_COMMENT, 0, apiResponse)); dialog.dismiss(); } }); @@ -308,10 +346,13 @@ public class CommentListAdapter extends RecyclerView.Adapter - - + app:labelText="@string/add_public_comment" + app:secondaryColor="?attr/colorAccent" + app:primaryColor="?attr/colorAccent" + > + + + android:src="@drawable/ic_baseline_send_24" /> - - + app:labelText="@string/add_public_reply" + app:secondaryColor="?attr/colorAccent" + app:primaryColor="?attr/colorAccent" + > + + + /> + + + + + + + + + + + + + + + +