diff --git a/app/src/main/java/io/lbry/browser/adapter/CommentListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/CommentListAdapter.java new file mode 100644 index 00000000..128b6a54 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/adapter/CommentListAdapter.java @@ -0,0 +1,52 @@ +package io.lbry.browser.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.List; + +import androidx.recyclerview.widget.RecyclerView; +import io.lbry.browser.R; +import io.lbry.browser.model.Comment; + +public class CommentListAdapter extends RecyclerView.Adapter { + private List items; + private Context context; + + public CommentListAdapter(List items, Context context) { + this.items = items; + this.context = context; + } + + @Override + public int getItemCount() { + return items != null ? items.size() : 0; + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + protected TextView channelName; + protected TextView commentText; + + public ViewHolder (View v) { + super(v); + channelName = v.findViewById(R.id.comment_channel_name); + commentText = v.findViewById(R.id.comment_text); + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(context).inflate(R.layout.list_item_comment, parent, false); + return new CommentListAdapter.ViewHolder(v); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Comment comment = items.get(position); + holder.channelName.setText(comment.getChannelName()); + holder.commentText.setText(comment.getText()); + } +} \ No newline at end of file diff --git a/app/src/main/java/io/lbry/browser/model/Comment.java b/app/src/main/java/io/lbry/browser/model/Comment.java new file mode 100644 index 00000000..c1f6ca72 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/model/Comment.java @@ -0,0 +1,40 @@ +package io.lbry.browser.model; + +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +import lombok.Data; + +@Data +public class Comment { + private final String channelName, text, id, parentId; + + public Comment(String channelName, String text, String id, String parentId) { + this.channelName = channelName; + this.text = text; + this.id = id; + this.parentId = parentId; + } + + public static Comment fromJSONObject(JSONObject jsonObject) { + try { + String parentId = null; + if (jsonObject.has("parent_id")) { + parentId = jsonObject.getString("parent_id"); + } + + return new Comment( + jsonObject.getString("channel_name"), + jsonObject.getString("comment"), + jsonObject.getString("comment_id"), + parentId + ); + } catch (JSONException ex) { + // TODO: Throw exception + Log.e("Comments", ex.toString()); + return null; + } + } +} diff --git a/app/src/main/java/io/lbry/browser/tasks/CommentListHandler.java b/app/src/main/java/io/lbry/browser/tasks/CommentListHandler.java new file mode 100644 index 00000000..a84a8585 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/CommentListHandler.java @@ -0,0 +1,10 @@ +package io.lbry.browser.tasks; + +import java.util.List; + +import io.lbry.browser.model.Comment; + +public interface CommentListHandler { + void onSuccess(List comments); + void onError(Exception error); +} diff --git a/app/src/main/java/io/lbry/browser/tasks/CommentListTask.java b/app/src/main/java/io/lbry/browser/tasks/CommentListTask.java new file mode 100644 index 00000000..e64f0308 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/CommentListTask.java @@ -0,0 +1,77 @@ +package io.lbry.browser.tasks; + +import android.os.AsyncTask; +import android.view.View; +import android.widget.ProgressBar; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.lbry.browser.model.Comment; +import io.lbry.browser.utils.Helper; +import io.lbry.browser.utils.Lbry; + +public class CommentListTask extends AsyncTask> { + private final int page; + private final int pageSize; + private final String claim; + private ProgressBar progressBar; + private CommentListHandler handler; + private Exception error; + + public CommentListTask(int page, int pageSize, String claim, ProgressBar progressBar, CommentListHandler handler) { + this.page = page; + this.pageSize = pageSize; + this.claim = claim; + this.progressBar = progressBar; + this.handler = handler; + } + + protected void onPreExecute() { + Helper.setViewVisibility(progressBar, View.VISIBLE); + } + + protected List doInBackground(Void... voids) { + List comments = null; + + try { + Map options = new HashMap<>(); + + options.put("claim_id", claim); + options.put("page", page); + options.put("page_size", pageSize); + options.put("include_replies", false); + options.put("is_channel_signature_valid", true); + options.put("visible", true); + options.put("hidden", false); + + JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_COMMENT_LIST, options); + JSONArray items = result.getJSONArray("items"); + comments = new ArrayList<>(); + for (int i = 0; i < items.length(); i++) { + comments.add(Comment.fromJSONObject(items.getJSONObject(i))); + } + } catch (Exception ex) { + error = ex; + } + return comments; + } + + protected void onPostExecute(List comments) { + Helper.setViewVisibility(progressBar, View.GONE); + if (handler != null) { + if (comments != null && error == null) { + handler.onSuccess(comments); + } else { + handler.onError(error); + if (error != null) { + } + } + } + } +} diff --git a/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java b/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java index fc32c947..f4c1674d 100644 --- a/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java @@ -89,6 +89,7 @@ import java.util.concurrent.TimeUnit; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.ClaimListAdapter; +import io.lbry.browser.adapter.CommentListAdapter; import io.lbry.browser.adapter.TagListAdapter; import io.lbry.browser.dialog.RepostClaimDialogFragment; import io.lbry.browser.dialog.SendTipDialogFragment; @@ -102,6 +103,7 @@ import io.lbry.browser.listener.StoragePermissionListener; import io.lbry.browser.listener.WalletBalanceListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.ClaimCacheKey; +import io.lbry.browser.model.Comment; import io.lbry.browser.model.Fee; import io.lbry.browser.model.LbryFile; import io.lbry.browser.model.NavMenuItem; @@ -110,6 +112,8 @@ import io.lbry.browser.model.UrlSuggestion; import io.lbry.browser.model.WalletBalance; import io.lbry.browser.model.lbryinc.Reward; import io.lbry.browser.model.lbryinc.Subscription; +import io.lbry.browser.tasks.CommentListHandler; +import io.lbry.browser.tasks.CommentListTask; import io.lbry.browser.tasks.GenericTaskHandler; import io.lbry.browser.tasks.LighthouseSearchTask; import io.lbry.browser.tasks.ReadTextFileTask; @@ -164,6 +168,7 @@ public class FileViewFragment extends BaseFragment implements private Claim claim; private String currentUrl; private ClaimListAdapter relatedContentAdapter; + private CommentListAdapter commentListAdapter; private BroadcastReceiver sdkReceiver; private Player.EventListener fileViewPlayerListener; @@ -317,6 +322,7 @@ public class FileViewFragment extends BaseFragment implements if (claim != null) { Helper.saveViewHistory(currentUrl, claim); checkAndLoadRelatedContent(); + checkAndLoadComments(); renderClaim(); if (claim.getFile() == null) { loadFile(); @@ -451,6 +457,7 @@ public class FileViewFragment extends BaseFragment implements loadFile(); } checkOwnClaim(); + checkAndLoadComments(); } private String getStreamingUrl() { @@ -532,6 +539,7 @@ public class FileViewFragment extends BaseFragment implements if (claim != null) { Helper.saveViewHistory(url, claim); checkAndLoadRelatedContent(); + checkAndLoadComments(); renderClaim(); } } @@ -571,7 +579,7 @@ public class FileViewFragment extends BaseFragment implements loadAndScheduleDurations(); } - if (Lbry.SDK_READY) { + if (!Lbry.SDK_READY) { if (context instanceof MainActivity) { ((MainActivity) context).addSdkStatusListener(this); } @@ -652,6 +660,7 @@ public class FileViewFragment extends BaseFragment implements loadFile(); checkAndLoadRelatedContent(); + checkAndLoadComments(); renderClaim(); } else { // render nothing at location @@ -989,9 +998,13 @@ public class FileViewFragment extends BaseFragment implements }); RecyclerView relatedContentList = root.findViewById(R.id.file_view_related_content_list); + RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list); relatedContentList.setNestedScrollingEnabled(false); - LinearLayoutManager llm = new LinearLayoutManager(getContext()); - relatedContentList.setLayoutManager(llm); + commentsList.setNestedScrollingEnabled(false); + LinearLayoutManager relatedContentListLLM = new LinearLayoutManager(getContext()); + LinearLayoutManager commentsListLLM = new LinearLayoutManager(getContext()); + relatedContentList.setLayoutManager(relatedContentListLLM); + commentsList.setLayoutManager(commentsListLLM); } private void deleteCurrentClaim() { @@ -1317,6 +1330,22 @@ public class FileViewFragment extends BaseFragment implements } } + private void checkAndLoadComments() { + View root = getView(); + if (root != null) { + RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list); + if (commentsList == null || commentsList.getAdapter() == null || commentsList.getAdapter().getItemCount() == 0) { + TextView commentsSDKInitializing = root.findViewById(R.id.file_view_comments_sdk_initializing); + if (Lbry.SDK_READY) { + Helper.setViewVisibility(commentsSDKInitializing, View.GONE); + loadComments(); + } else { + Helper.setViewVisibility(commentsSDKInitializing, View.VISIBLE); + } + } + } + } + private void showUnsupportedView() { View root = getView(); if (root != null) { @@ -1856,6 +1885,39 @@ public class FileViewFragment extends BaseFragment implements } } + private void loadComments() { + View root = getView(); + ProgressBar relatedLoading = root.findViewById(R.id.file_view_comments_progress); + if (claim != null && root != null) { + CommentListTask relatedTask = new CommentListTask(1, 999, claim.getClaimId(), relatedLoading, new CommentListHandler() { + @Override + public void onSuccess(List comments) { + Context ctx = getContext(); + if (ctx != null) { + commentListAdapter = new CommentListAdapter(comments, ctx); + + View v = getView(); + if (v != null) { + RecyclerView relatedContentList = root.findViewById(R.id.file_view_comments_list); + relatedContentList.setAdapter(commentListAdapter); + commentListAdapter.notifyDataSetChanged(); + + Helper.setViewVisibility( + v.findViewById(R.id.file_view_no_comments), + commentListAdapter == null || commentListAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE); + } + } + } + + @Override + public void onError(Exception error) { + + } + }); + relatedTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + public boolean onBackPressed() { if (isInFullscreenMode()) { disableFullScreenMode(); diff --git a/app/src/main/java/io/lbry/browser/utils/Lbry.java b/app/src/main/java/io/lbry/browser/utils/Lbry.java index 4e7c8046..c9ff7460 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbry.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbry.java @@ -102,6 +102,8 @@ public final class Lbry { public static final String METHOD_STREAM_ABANDON = "stream_abandon"; public static final String METHOD_STREAM_REPOST = "stream_repost"; + public static final String METHOD_COMMENT_LIST = "comment_list"; + public static KeyStore KEYSTORE; public static boolean SDK_READY = false; diff --git a/app/src/main/res/layout/fragment_file_view.xml b/app/src/main/res/layout/fragment_file_view.xml index ad9a6cc4..9e335b04 100644 --- a/app/src/main/res/layout/fragment_file_view.xml +++ b/app/src/main/res/layout/fragment_file_view.xml @@ -480,23 +480,24 @@ android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp"> + + android:layout_height="wrap_content" + android:clickable="true" + android:orientation="vertical"> + + android:textColor="@color/lbryGreen" + android:textFontWeight="600" + android:textSize="14sp" /> + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/list_item_comment.xml b/app/src/main/res/layout/list_item_comment.xml new file mode 100644 index 00000000..a4e78a55 --- /dev/null +++ b/app/src/main/res/layout/list_item_comment.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3774caca..6d742a0d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -59,6 +59,9 @@ Report Loading decentralized data... Related Content + Comments + No comments to display. + Comments will display once the background service is done initializing. Share LBRY content View Play