Compare commits
4 commits
master
...
commenting
Author | SHA1 | Date | |
---|---|---|---|
|
4685791f9c | ||
|
b1e8371d28 | ||
|
a7101778d2 | ||
|
a0c21c44cb |
22 changed files with 2041 additions and 336 deletions
|
@ -297,17 +297,13 @@ public class ClaimListAdapter extends RecyclerView.Adapter<ClaimListAdapter.View
|
||||||
return new ClaimListAdapter.ViewHolder(v);
|
return new ClaimListAdapter.ViewHolder(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScaledValue(int value) {
|
|
||||||
return (int) (value * scale + 0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ClaimListAdapter.ViewHolder vh, int position) {
|
public void onBindViewHolder(ClaimListAdapter.ViewHolder vh, int position) {
|
||||||
int type = getItemViewType(position);
|
int type = getItemViewType(position);
|
||||||
int paddingTop = position == 0 ? 16 : 8;
|
int paddingTop = position == 0 ? 16 : 8;
|
||||||
int paddingBottom = position == getItemCount() - 1 ? 16 : 8;
|
int paddingBottom = position == getItemCount() - 1 ? 16 : 8;
|
||||||
int paddingTopScaled = getScaledValue(paddingTop);
|
int paddingTopScaled = Helper.getScaledValue(paddingTop, scale);
|
||||||
int paddingBottomScaled = getScaledValue(paddingBottom);
|
int paddingBottomScaled = Helper.getScaledValue(paddingBottom, scale);
|
||||||
vh.itemView.setPadding(vh.itemView.getPaddingLeft(), paddingTopScaled, vh.itemView.getPaddingRight(), paddingBottomScaled);
|
vh.itemView.setPadding(vh.itemView.getPaddingLeft(), paddingTopScaled, vh.itemView.getPaddingRight(), paddingBottomScaled);
|
||||||
|
|
||||||
Claim original = items.get(position);
|
Claim original = items.get(position);
|
||||||
|
|
|
@ -1,24 +1,64 @@
|
||||||
package io.lbry.browser.adapter;
|
package io.lbry.browser.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
|
import io.lbry.browser.model.Claim;
|
||||||
|
import io.lbry.browser.model.ClaimCacheKey;
|
||||||
import io.lbry.browser.model.Comment;
|
import io.lbry.browser.model.Comment;
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.LbryUri;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
public class CommentListAdapter extends RecyclerView.Adapter<CommentListAdapter.ViewHolder> {
|
public class CommentListAdapter extends RecyclerView.Adapter<CommentListAdapter.ViewHolder> {
|
||||||
private List<Comment> items;
|
private List<Comment> items;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private boolean nested;
|
||||||
|
private float scale;
|
||||||
|
@Setter
|
||||||
|
private ClaimListAdapter.ClaimListItemListener listener;
|
||||||
|
@Setter
|
||||||
|
private ReplyClickListener replyListener;
|
||||||
|
|
||||||
public CommentListAdapter(List<Comment> items, Context context) {
|
public CommentListAdapter(List<Comment> items, Context context) {
|
||||||
this.items = items;
|
this(items, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommentListAdapter(List<Comment> items, Context context, boolean nested) {
|
||||||
|
this.items = new ArrayList<>(items);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.nested = nested;
|
||||||
|
if (context != null) {
|
||||||
|
scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
}
|
||||||
|
for (Comment item : this.items) {
|
||||||
|
ClaimCacheKey key = new ClaimCacheKey();
|
||||||
|
key.setClaimId(item.getChannelId());
|
||||||
|
if (Lbry.claimCache.containsKey(key)) {
|
||||||
|
item.setPoster(Lbry.claimCache.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearItems() {
|
||||||
|
items.clear();
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,14 +66,90 @@ public class CommentListAdapter extends RecyclerView.Adapter<CommentListAdapter.
|
||||||
return items != null ? items.size() : 0;
|
return items != null ? items.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getClaimUrlsToResolve() {
|
||||||
|
List<String> urls = new ArrayList<>();
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
Comment item = items.get(i);
|
||||||
|
if (item.getPoster() == null) {
|
||||||
|
LbryUri url = LbryUri.tryParse(String.format("%s#%s", item.getChannelName(), item.getChannelId()));
|
||||||
|
if (url != null && !urls.contains(url.toString())) {
|
||||||
|
urls.add(url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.getReplies().size() > 0) {
|
||||||
|
for (int j = 0; j < item.getReplies().size(); j++) {
|
||||||
|
Comment reply = item.getReplies().get(j);
|
||||||
|
if (reply.getPoster() == null) {
|
||||||
|
LbryUri url = LbryUri.tryParse(String.format("%s#%s", reply.getChannelName(), reply.getChannelId()));
|
||||||
|
if (url != null && !urls.contains(url.toString())) {
|
||||||
|
urls.add(url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
protected TextView channelName;
|
protected TextView channelName;
|
||||||
protected TextView commentText;
|
protected TextView commentText;
|
||||||
|
protected ImageView thumbnailView;
|
||||||
|
protected View noThumbnailView;
|
||||||
|
protected TextView alphaView;
|
||||||
|
protected TextView commentTimeView;
|
||||||
|
protected View replyLink;
|
||||||
|
protected RecyclerView repliesList;
|
||||||
|
|
||||||
public ViewHolder (View v) {
|
public ViewHolder (View v) {
|
||||||
super(v);
|
super(v);
|
||||||
channelName = v.findViewById(R.id.comment_channel_name);
|
channelName = v.findViewById(R.id.comment_channel_name);
|
||||||
|
commentTimeView = v.findViewById(R.id.comment_time);
|
||||||
commentText = v.findViewById(R.id.comment_text);
|
commentText = v.findViewById(R.id.comment_text);
|
||||||
|
replyLink = v.findViewById(R.id.comment_reply_link);
|
||||||
|
thumbnailView = v.findViewById(R.id.comment_thumbnail);
|
||||||
|
noThumbnailView = v.findViewById(R.id.comment_no_thumbnail);
|
||||||
|
alphaView = v.findViewById(R.id.comment_thumbnail_alpha);
|
||||||
|
repliesList = v.findViewById(R.id.comment_replies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(int index, Comment comment) {
|
||||||
|
if (!items.contains(comment)) {
|
||||||
|
items.add(index, comment);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addReply(Comment comment) {
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
Comment parent = items.get(i);
|
||||||
|
if (parent.getId().equalsIgnoreCase(comment.getParentId())) {
|
||||||
|
parent.addReply(comment);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePosterForComment(String channelId, Claim channel) {
|
||||||
|
for (int i = 0 ; i < items.size(); i++) {
|
||||||
|
Comment item = items.get(i);
|
||||||
|
List<Comment> replies = item.getReplies();
|
||||||
|
if (replies != null && replies.size() > 0) {
|
||||||
|
for (int j = 0; j < replies.size(); j++) {
|
||||||
|
Comment reply = item.getReplies().get(j);
|
||||||
|
if (channelId.equalsIgnoreCase(reply.getChannelId())) {
|
||||||
|
reply.setPoster(channel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelId.equalsIgnoreCase(item.getChannelId())) {
|
||||||
|
item.setPoster(channel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +162,57 @@ public class CommentListAdapter extends RecyclerView.Adapter<CommentListAdapter.
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
Comment comment = items.get(position);
|
Comment comment = items.get(position);
|
||||||
|
holder.itemView.setPadding(
|
||||||
|
nested ? Helper.getScaledValue(56, scale) : holder.itemView.getPaddingLeft(),
|
||||||
|
holder.itemView.getPaddingTop(),
|
||||||
|
nested ? 0 : holder.itemView.getPaddingRight(),
|
||||||
|
holder.itemView.getPaddingBottom());
|
||||||
|
|
||||||
holder.channelName.setText(comment.getChannelName());
|
holder.channelName.setText(comment.getChannelName());
|
||||||
|
holder.commentTimeView.setText(DateUtils.getRelativeTimeSpanString(
|
||||||
|
(comment.getTimestamp() * 1000), System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
|
||||||
holder.commentText.setText(comment.getText());
|
holder.commentText.setText(comment.getText());
|
||||||
|
holder.replyLink.setVisibility(!nested ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
boolean hasThumbnail = comment.getPoster() != null && !Helper.isNullOrEmpty(comment.getPoster().getThumbnailUrl());
|
||||||
|
holder.thumbnailView.setVisibility(hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
holder.noThumbnailView.setVisibility(!hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
int bgColor = Helper.generateRandomColorForValue(comment.getChannelId());
|
||||||
|
Helper.setIconViewBackgroundColor(holder.noThumbnailView, bgColor, false, context);
|
||||||
|
if (hasThumbnail) {
|
||||||
|
Glide.with(context.getApplicationContext()).asBitmap().load(comment.getPoster().getThumbnailUrl()).
|
||||||
|
apply(RequestOptions.circleCropTransform()).into(holder.thumbnailView);
|
||||||
|
}
|
||||||
|
holder.alphaView.setText(comment.getChannelName() != null ? comment.getChannelName().substring(1, 2).toUpperCase() : null);
|
||||||
|
List<Comment> replies = comment.getReplies();
|
||||||
|
boolean hasReplies = replies != null && replies.size() > 0;
|
||||||
|
if (hasReplies) {
|
||||||
|
holder.repliesList.setLayoutManager(new LinearLayoutManager(context));
|
||||||
|
holder.repliesList.setAdapter(new CommentListAdapter(replies, context, true));
|
||||||
|
} else {
|
||||||
|
holder.repliesList.setAdapter(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.channelName.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (listener != null && comment.getPoster() != null) {
|
||||||
|
listener.onClaimClicked(comment.getPoster());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.replyLink.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (replyListener != null) {
|
||||||
|
replyListener.onReplyClicked(comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ReplyClickListener {
|
||||||
|
void onReplyClicked(Comment comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,21 +1,48 @@
|
||||||
package io.lbry.browser.model;
|
package io.lbry.browser.model;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class Comment {
|
public class Comment {
|
||||||
private final String channelName, text, id, parentId;
|
public static final double COST = 0.25;
|
||||||
|
public static final int MAX_LENGTH = 2000;
|
||||||
|
|
||||||
public Comment(String channelName, String text, String id, String parentId) {
|
private Claim poster;
|
||||||
|
private String claimId;
|
||||||
|
private List<Comment> replies;
|
||||||
|
private long timestamp;
|
||||||
|
private String channelId;
|
||||||
|
private String channelName, text, id, parentId;
|
||||||
|
|
||||||
|
public Comment(String channelId, String channelName, String text, String id, String parentId) {
|
||||||
|
this.channelId = channelId;
|
||||||
this.channelName = channelName;
|
this.channelName = channelName;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.parentId = parentId;
|
this.parentId = parentId;
|
||||||
|
|
||||||
|
this.replies = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comment() {
|
||||||
|
replies = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addReply(Comment reply) {
|
||||||
|
if (replies == null) {
|
||||||
|
replies = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (!replies.contains(reply)) {
|
||||||
|
replies.add(reply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Comment fromJSONObject(JSONObject jsonObject) {
|
public static Comment fromJSONObject(JSONObject jsonObject) {
|
||||||
|
@ -25,15 +52,17 @@ public class Comment {
|
||||||
parentId = jsonObject.getString("parent_id");
|
parentId = jsonObject.getString("parent_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Comment(
|
Comment comment = new Comment(
|
||||||
|
Helper.getJSONString("channel_id", null, jsonObject),
|
||||||
jsonObject.getString("channel_name"),
|
jsonObject.getString("channel_name"),
|
||||||
jsonObject.getString("comment"),
|
jsonObject.getString("comment"),
|
||||||
jsonObject.getString("comment_id"),
|
jsonObject.getString("comment_id"),
|
||||||
parentId
|
parentId
|
||||||
);
|
);
|
||||||
|
comment.setClaimId(Helper.getJSONString("claim_id", null, jsonObject));
|
||||||
|
comment.setTimestamp(Helper.getJSONLong("timestamp", 0, jsonObject));
|
||||||
|
return comment;
|
||||||
} catch (JSONException ex) {
|
} catch (JSONException ex) {
|
||||||
// TODO: Throw exception
|
|
||||||
Log.e("Comments", ex.toString());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
package io.lbry.browser.tasks;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import io.lbry.browser.exceptions.ApiCallException;
|
||||||
|
import io.lbry.browser.model.Comment;
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.Lbryio;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class CommentCreateWithTipTask extends AsyncTask<Void, Void, Comment> {
|
||||||
|
private static final String STATUS_ENDPOINT = "https://comments.lbry.com";
|
||||||
|
|
||||||
|
private Comment comment;
|
||||||
|
private BigDecimal amount;
|
||||||
|
private View progressView;
|
||||||
|
private CommentCreateWithTipHandler handler;
|
||||||
|
private Exception error;
|
||||||
|
|
||||||
|
public CommentCreateWithTipTask(Comment comment, BigDecimal amount, View progressView, CommentCreateWithTipHandler handler) {
|
||||||
|
this.comment = comment;
|
||||||
|
this.amount = amount;
|
||||||
|
this.progressView = progressView;
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPreExecute() {
|
||||||
|
Helper.setViewVisibility(progressView, View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comment doInBackground(Void... params) {
|
||||||
|
Comment createdComment = null;
|
||||||
|
try {
|
||||||
|
// check comments status endpoint
|
||||||
|
Request request = new Request.Builder().url(STATUS_ENDPOINT).build();
|
||||||
|
OkHttpClient client = new OkHttpClient.Builder().
|
||||||
|
writeTimeout(30, TimeUnit.SECONDS).
|
||||||
|
readTimeout(30, TimeUnit.SECONDS).
|
||||||
|
build();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
JSONObject status = new JSONObject(response.body().string());
|
||||||
|
String statusText = Helper.getJSONString("text", null, status);
|
||||||
|
boolean isRunning = Helper.getJSONBoolean("is_running", false, status);
|
||||||
|
if (!"ok".equalsIgnoreCase(statusText) || !isRunning) {
|
||||||
|
throw new ApiCallException("The comment server is not available at this time. Please try again later.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> options = new HashMap<>();
|
||||||
|
options.put("blocking", true);
|
||||||
|
options.put("claim_id", comment.getClaimId());
|
||||||
|
options.put("amount", new DecimalFormat(Helper.SDK_AMOUNT_FORMAT, new DecimalFormatSymbols(Locale.US)).format(amount.doubleValue()));
|
||||||
|
options.put("tip", true);
|
||||||
|
Lbry.genericApiCall(Lbry.METHOD_SUPPORT_CREATE, options);
|
||||||
|
|
||||||
|
options = new HashMap<>();
|
||||||
|
options.put("comment", comment.getText());
|
||||||
|
options.put("claim_id", comment.getClaimId());
|
||||||
|
options.put("channel_id", comment.getChannelId());
|
||||||
|
options.put("channel_name", comment.getChannelName());
|
||||||
|
if (!Helper.isNullOrEmpty(comment.getParentId())) {
|
||||||
|
options.put("parent_id", comment.getParentId());
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_COMMENT_CREATE, options);
|
||||||
|
createdComment = Comment.fromJSONObject(jsonObject);
|
||||||
|
} catch (ApiCallException | ClassCastException | IOException | JSONException ex) {
|
||||||
|
error = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createdComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Comment createdComment) {
|
||||||
|
Helper.setViewVisibility(progressView, View.GONE);
|
||||||
|
if (handler != null) {
|
||||||
|
if (createdComment != null) {
|
||||||
|
handler.onSuccess(createdComment);
|
||||||
|
} else {
|
||||||
|
handler.onError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CommentCreateWithTipHandler {
|
||||||
|
void onSuccess(Comment createdComment);
|
||||||
|
void onError(Exception error);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,6 @@ import java.util.List;
|
||||||
import io.lbry.browser.model.Comment;
|
import io.lbry.browser.model.Comment;
|
||||||
|
|
||||||
public interface CommentListHandler {
|
public interface CommentListHandler {
|
||||||
void onSuccess(List<Comment> comments);
|
void onSuccess(List<Comment> comments, boolean hasReachedEnd);
|
||||||
void onError(Exception error);
|
void onError(Exception error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,27 @@ public class CommentListTask extends AsyncTask<Void, Void, List<Comment>> {
|
||||||
|
|
||||||
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_COMMENT_LIST, options);
|
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_COMMENT_LIST, options);
|
||||||
JSONArray items = result.getJSONArray("items");
|
JSONArray items = result.getJSONArray("items");
|
||||||
|
|
||||||
|
List<Comment> children = new ArrayList<>();
|
||||||
comments = new ArrayList<>();
|
comments = new ArrayList<>();
|
||||||
for (int i = 0; i < items.length(); i++) {
|
for (int i = 0; i < items.length(); i++) {
|
||||||
comments.add(Comment.fromJSONObject(items.getJSONObject(i)));
|
Comment comment = Comment.fromJSONObject(items.getJSONObject(i));
|
||||||
|
if (comment != null) {
|
||||||
|
if (!Helper.isNullOrEmpty(comment.getParentId())) {
|
||||||
|
children.add(comment);
|
||||||
|
} else {
|
||||||
|
comments.add(comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Comment child : children) {
|
||||||
|
for (Comment parent : comments) {
|
||||||
|
if (parent.getId().equalsIgnoreCase(child.getParentId())) {
|
||||||
|
parent.addReply(child);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
error = ex;
|
error = ex;
|
||||||
|
@ -65,12 +83,10 @@ public class CommentListTask extends AsyncTask<Void, Void, List<Comment>> {
|
||||||
protected void onPostExecute(List<Comment> comments) {
|
protected void onPostExecute(List<Comment> comments) {
|
||||||
Helper.setViewVisibility(progressBar, View.GONE);
|
Helper.setViewVisibility(progressBar, View.GONE);
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
if (comments != null && error == null) {
|
if (comments != null) {
|
||||||
handler.onSuccess(comments);
|
handler.onSuccess(comments, comments.size() < pageSize);
|
||||||
} else {
|
} else {
|
||||||
handler.onError(error);
|
handler.onError(error);
|
||||||
if (error != null) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class SupportCreateTask extends AsyncTask<Void, Void, Boolean> {
|
||||||
protected Boolean doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
Map<String, Object> options = new HashMap<>();
|
Map<String, Object> options = new HashMap<>();
|
||||||
|
options.put("blocking", true);
|
||||||
options.put("claim_id", claimId);
|
options.put("claim_id", claimId);
|
||||||
options.put("amount", new DecimalFormat(Helper.SDK_AMOUNT_FORMAT, new DecimalFormatSymbols(Locale.US)).format(amount.doubleValue()));
|
options.put("amount", new DecimalFormat(Helper.SDK_AMOUNT_FORMAT, new DecimalFormatSymbols(Locale.US)).format(amount.doubleValue()));
|
||||||
options.put("tip", tip);
|
options.put("tip", tip);
|
||||||
|
|
|
@ -1,19 +1,36 @@
|
||||||
package io.lbry.browser.ui;
|
package io.lbry.browser.ui;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.AppCompatSpinner;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.lbry.browser.BuildConfig;
|
||||||
import io.lbry.browser.MainActivity;
|
import io.lbry.browser.MainActivity;
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
|
import io.lbry.browser.adapter.InlineChannelSpinnerAdapter;
|
||||||
|
import io.lbry.browser.model.Claim;
|
||||||
import io.lbry.browser.model.WalletBalance;
|
import io.lbry.browser.model.WalletBalance;
|
||||||
|
import io.lbry.browser.tasks.claim.ChannelCreateUpdateTask;
|
||||||
|
import io.lbry.browser.tasks.claim.ClaimResultHandler;
|
||||||
|
import io.lbry.browser.tasks.lbryinc.LogPublishTask;
|
||||||
import io.lbry.browser.ui.wallet.RewardsFragment;
|
import io.lbry.browser.ui.wallet.RewardsFragment;
|
||||||
import io.lbry.browser.utils.Helper;
|
import io.lbry.browser.utils.Helper;
|
||||||
import io.lbry.browser.utils.Lbry;
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.LbryAnalytics;
|
||||||
|
import io.lbry.browser.utils.LbryUri;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -94,4 +111,132 @@ public class BaseFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showError(String message) {
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
Snackbar.make(getView(), message, Snackbar.LENGTH_LONG).
|
||||||
|
setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupInlineChannelCreator(
|
||||||
|
View container,
|
||||||
|
TextInputEditText inputChannelName,
|
||||||
|
TextInputEditText inputDeposit,
|
||||||
|
View inlineBalanceView,
|
||||||
|
TextView inlineBalanceValue,
|
||||||
|
View linkCancel,
|
||||||
|
MaterialButton buttonCreate,
|
||||||
|
View progressView,
|
||||||
|
AppCompatSpinner channelSpinner,
|
||||||
|
InlineChannelSpinnerAdapter channelSpinnerAdapter) {
|
||||||
|
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onFocusChange(View view, boolean hasFocus) {
|
||||||
|
Helper.setViewVisibility(inlineBalanceView, hasFocus ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
linkCancel.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Helper.setViewText(inputChannelName, null);
|
||||||
|
Helper.setViewText(inputDeposit, null);
|
||||||
|
Helper.setViewVisibility(container, View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonCreate.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
// validate deposit and channel name
|
||||||
|
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
|
||||||
|
Claim claimToSave = new Claim();
|
||||||
|
claimToSave.setName(channelNameString);
|
||||||
|
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
|
||||||
|
String depositString = Helper.getValue(inputDeposit.getText());
|
||||||
|
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
|
||||||
|
showError(getString(R.string.please_enter_channel_name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!LbryUri.isNameValid(channelName)) {
|
||||||
|
showError(getString(R.string.channel_name_invalid_characters));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Helper.channelExists(channelName)) {
|
||||||
|
showError(getString(R.string.channel_name_already_created));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double depositAmount = 0;
|
||||||
|
try {
|
||||||
|
depositAmount = Double.valueOf(depositString);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
// pass
|
||||||
|
showError(getString(R.string.please_enter_valid_deposit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depositAmount == 0) {
|
||||||
|
String error = getResources().getQuantityString(R.plurals.min_deposit_required, depositAmount == 1 ? 1 : 2, String.valueOf(Helper.MIN_DEPOSIT));
|
||||||
|
showError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Lbry.walletBalance == null || Lbry.walletBalance.getAvailable().doubleValue() < depositAmount) {
|
||||||
|
showError(getString(R.string.deposit_more_than_balance));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelCreateUpdateTask task = new ChannelCreateUpdateTask(
|
||||||
|
claimToSave, new BigDecimal(depositString), false, progressView, new ClaimResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void beforeStart() {
|
||||||
|
Helper.setViewEnabled(inputChannelName, false);
|
||||||
|
Helper.setViewEnabled(inputDeposit, false);
|
||||||
|
Helper.setViewEnabled(buttonCreate, false);
|
||||||
|
Helper.setViewEnabled(linkCancel, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Claim claimResult) {
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
LogPublishTask logPublishTask = new LogPublishTask(claimResult);
|
||||||
|
logPublishTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel created
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("claim_id", claimResult.getClaimId());
|
||||||
|
bundle.putString("claim_name", claimResult.getName());
|
||||||
|
LbryAnalytics.logEvent(LbryAnalytics.EVENT_CHANNEL_CREATE, bundle);
|
||||||
|
|
||||||
|
// add the claim to the channel list and set it as the selected item
|
||||||
|
if (channelSpinnerAdapter != null) {
|
||||||
|
channelSpinnerAdapter.add(claimResult);
|
||||||
|
}
|
||||||
|
if (channelSpinner != null && channelSpinnerAdapter != null) {
|
||||||
|
channelSpinner.setSelection(channelSpinnerAdapter.getCount() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.setViewEnabled(inputChannelName, true);
|
||||||
|
Helper.setViewEnabled(inputDeposit, true);
|
||||||
|
Helper.setViewEnabled(buttonCreate, true);
|
||||||
|
Helper.setViewEnabled(linkCancel, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
Helper.setViewEnabled(inputChannelName, true);
|
||||||
|
Helper.setViewEnabled(inputDeposit, true);
|
||||||
|
Helper.setViewEnabled(buttonCreate, true);
|
||||||
|
Helper.setViewEnabled(linkCancel, true);
|
||||||
|
showError(error.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Helper.setViewText(inlineBalanceValue, Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,705 @@
|
||||||
|
package io.lbry.browser.ui.channel;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.AppCompatSpinner;
|
||||||
|
import androidx.core.text.HtmlCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.lbry.browser.BuildConfig;
|
||||||
|
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.InlineChannelSpinnerAdapter;
|
||||||
|
import io.lbry.browser.listener.SdkStatusListener;
|
||||||
|
import io.lbry.browser.listener.WalletBalanceListener;
|
||||||
|
import io.lbry.browser.model.Claim;
|
||||||
|
import io.lbry.browser.model.Comment;
|
||||||
|
import io.lbry.browser.model.WalletBalance;
|
||||||
|
import io.lbry.browser.tasks.CommentCreateWithTipTask;
|
||||||
|
import io.lbry.browser.tasks.CommentListHandler;
|
||||||
|
import io.lbry.browser.tasks.CommentListTask;
|
||||||
|
import io.lbry.browser.tasks.claim.ChannelCreateUpdateTask;
|
||||||
|
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
|
||||||
|
import io.lbry.browser.tasks.claim.ClaimListTask;
|
||||||
|
import io.lbry.browser.tasks.claim.ClaimResultHandler;
|
||||||
|
import io.lbry.browser.tasks.claim.ResolveTask;
|
||||||
|
import io.lbry.browser.tasks.lbryinc.LogPublishTask;
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.LbryAnalytics;
|
||||||
|
import io.lbry.browser.utils.LbryUri;
|
||||||
|
import io.lbry.browser.utils.Lbryio;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class ChannelCommentsFragment extends Fragment implements SdkStatusListener, WalletBalanceListener {
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private Claim claim;
|
||||||
|
private CommentListAdapter commentListAdapter;
|
||||||
|
|
||||||
|
private Comment replyToComment;
|
||||||
|
private View containerReplyToComment;
|
||||||
|
private TextView textReplyingTo;
|
||||||
|
private TextView textReplyToBody;
|
||||||
|
private View buttonClearReplyToComment;
|
||||||
|
|
||||||
|
private boolean postingComment;
|
||||||
|
private boolean fetchingChannels;
|
||||||
|
private View progressLoadingChannels;
|
||||||
|
private View progressPostComment;
|
||||||
|
private InlineChannelSpinnerAdapter commentChannelSpinnerAdapter;
|
||||||
|
private AppCompatSpinner commentChannelSpinner;
|
||||||
|
private TextInputEditText inputComment;
|
||||||
|
private TextView textCommentLimit;
|
||||||
|
private MaterialButton buttonPostComment;
|
||||||
|
private ImageView commentPostAsThumbnail;
|
||||||
|
private View commentPostAsNoThumbnail;
|
||||||
|
private TextView commentPostAsAlpha;
|
||||||
|
|
||||||
|
private View inlineChannelCreator;
|
||||||
|
private TextInputEditText inlineChannelCreatorInputName;
|
||||||
|
private TextInputEditText inlineChannelCreatorInputDeposit;
|
||||||
|
private View inlineChannelCreatorInlineBalance;
|
||||||
|
private TextView inlineChannelCreatorInlineBalanceValue;
|
||||||
|
private View inlineChannelCreatorCancelLink;
|
||||||
|
private View inlineChannelCreatorProgress;
|
||||||
|
private MaterialButton inlineChannelCreatorCreateButton;
|
||||||
|
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View root = inflater.inflate(R.layout.fragment_channel_comments, container, false);
|
||||||
|
|
||||||
|
containerReplyToComment = root.findViewById(R.id.comment_form_reply_to_container);
|
||||||
|
textReplyingTo = root.findViewById(R.id.comment_form_replying_to_text);
|
||||||
|
textReplyToBody = root.findViewById(R.id.comment_form_reply_to_body);
|
||||||
|
buttonClearReplyToComment = root.findViewById(R.id.comment_form_clear_reply_to);
|
||||||
|
|
||||||
|
commentChannelSpinner = root.findViewById(R.id.comment_form_channel_spinner);
|
||||||
|
progressLoadingChannels = root.findViewById(R.id.comment_form_channels_loading);
|
||||||
|
progressPostComment = root.findViewById(R.id.comment_form_post_progress);
|
||||||
|
inputComment = root.findViewById(R.id.comment_form_body);
|
||||||
|
textCommentLimit = root.findViewById(R.id.comment_form_text_limit);
|
||||||
|
buttonPostComment = root.findViewById(R.id.comment_form_post);
|
||||||
|
commentPostAsThumbnail = root.findViewById(R.id.comment_form_thumbnail);
|
||||||
|
commentPostAsNoThumbnail = root.findViewById(R.id.comment_form_no_thumbnail);
|
||||||
|
commentPostAsAlpha = root.findViewById(R.id.comment_form_thumbnail_alpha);
|
||||||
|
|
||||||
|
inlineChannelCreator = root.findViewById(R.id.container_inline_channel_form_create);
|
||||||
|
inlineChannelCreatorInputName = root.findViewById(R.id.inline_channel_form_input_name);
|
||||||
|
inlineChannelCreatorInputDeposit = root.findViewById(R.id.inline_channel_form_input_deposit);
|
||||||
|
inlineChannelCreatorInlineBalance = root.findViewById(R.id.inline_channel_form_inline_balance_container);
|
||||||
|
inlineChannelCreatorInlineBalanceValue = root.findViewById(R.id.inline_channel_form_inline_balance_value);
|
||||||
|
inlineChannelCreatorProgress = root.findViewById(R.id.inline_channel_form_create_progress);
|
||||||
|
inlineChannelCreatorCancelLink = root.findViewById(R.id.inline_channel_form_cancel_link);
|
||||||
|
inlineChannelCreatorCreateButton = root.findViewById(R.id.inline_channel_form_create_button);
|
||||||
|
|
||||||
|
RecyclerView commentList = root.findViewById(R.id.channel_comments_list);
|
||||||
|
commentList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
|
initCommentForm(root);
|
||||||
|
setupInlineChannelCreator(
|
||||||
|
inlineChannelCreator,
|
||||||
|
inlineChannelCreatorInputName,
|
||||||
|
inlineChannelCreatorInputDeposit,
|
||||||
|
inlineChannelCreatorInlineBalance,
|
||||||
|
inlineChannelCreatorInlineBalanceValue,
|
||||||
|
inlineChannelCreatorCancelLink,
|
||||||
|
inlineChannelCreatorCreateButton,
|
||||||
|
inlineChannelCreatorProgress,
|
||||||
|
commentChannelSpinner,
|
||||||
|
commentChannelSpinnerAdapter
|
||||||
|
);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Context context = getContext();
|
||||||
|
if (!Lbry.SDK_READY) {
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).addSdkStatusListener(this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onSdkReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).addWalletBalanceListener(this);
|
||||||
|
}
|
||||||
|
checkCommentSdkInitializing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
MainActivity activity = (MainActivity) context;
|
||||||
|
activity.removeSdkStatusListener(this);
|
||||||
|
activity.removeWalletBalanceListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCommentSdkInitializing() {
|
||||||
|
View root = getView();
|
||||||
|
if (root != null) {
|
||||||
|
TextView commentsSDKInitializing = root.findViewById(R.id.channel_comments_sdk_initializing);
|
||||||
|
Helper.setViewVisibility(commentsSDKInitializing, Lbry.SDK_READY ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSdkReady() {
|
||||||
|
fetchChannels();
|
||||||
|
checkAndLoadComments();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAndLoadComments() {
|
||||||
|
View root = getView();
|
||||||
|
if (root != null) {
|
||||||
|
checkCommentSdkInitializing();
|
||||||
|
RecyclerView commentsList = root.findViewById(R.id.channel_comments_list);
|
||||||
|
if (commentsList == null || commentsList.getAdapter() == null || commentsList.getAdapter().getItemCount() == 0) {
|
||||||
|
loadComments();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadComments() {
|
||||||
|
View root = getView();
|
||||||
|
ProgressBar relatedLoading = root.findViewById(R.id.channel_comments_progress);
|
||||||
|
if (claim != null && root != null) {
|
||||||
|
CommentListTask task = new CommentListTask(1, 500, claim.getClaimId(), relatedLoading, new CommentListHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Comment> comments, boolean hasReachedEnd) {
|
||||||
|
Context ctx = getContext();
|
||||||
|
View root = getView();
|
||||||
|
if (ctx != null && root != null) {
|
||||||
|
commentListAdapter = new CommentListAdapter(comments, ctx);
|
||||||
|
commentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() {
|
||||||
|
@Override
|
||||||
|
public void onClaimClicked(Claim claim) {
|
||||||
|
if (!Helper.isNullOrEmpty(claim.getName()) &&
|
||||||
|
claim.getName().startsWith("@") &&
|
||||||
|
ctx instanceof MainActivity) {
|
||||||
|
((MainActivity) ctx).openChannelClaim(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
commentListAdapter.setReplyListener(new CommentListAdapter.ReplyClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onReplyClicked(Comment comment) {
|
||||||
|
setReplyToComment(comment);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RecyclerView relatedContentList = root.findViewById(R.id.channel_comments_list);
|
||||||
|
relatedContentList.setAdapter(commentListAdapter);
|
||||||
|
commentListAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
checkNoComments();
|
||||||
|
resolveCommentPosters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveCommentPosters() {
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
List<String> urlsToResolve = new ArrayList<>(commentListAdapter.getClaimUrlsToResolve());
|
||||||
|
if (urlsToResolve.size() > 0) {
|
||||||
|
ResolveTask task = new ResolveTask(urlsToResolve, Lbry.SDK_CONNECTION_STRING, null, new ClaimListResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Claim> claims) {
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
for (Claim claim : claims) {
|
||||||
|
if (claim.getClaimId() != null) {
|
||||||
|
commentListAdapter.updatePosterForComment(claim.getClaimId(), claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commentListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
|
||||||
|
if (walletBalance != null && inlineChannelCreatorInlineBalanceValue != null) {
|
||||||
|
inlineChannelCreatorInlineBalanceValue.setText(Helper.shortCurrencyFormat(walletBalance.getAvailable().doubleValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchChannels() {
|
||||||
|
if (Lbry.ownChannels != null && Lbry.ownChannels.size() > 0) {
|
||||||
|
updateChannelList(Lbry.ownChannels);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchingChannels = true;
|
||||||
|
disableChannelSpinner();
|
||||||
|
ClaimListTask task = new ClaimListTask(Claim.TYPE_CHANNEL, progressLoadingChannels, new ClaimListResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Claim> claims) {
|
||||||
|
Lbry.ownChannels = new ArrayList<>(claims);
|
||||||
|
updateChannelList(Lbry.ownChannels);
|
||||||
|
enableChannelSpinner();
|
||||||
|
fetchingChannels = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
enableChannelSpinner();
|
||||||
|
fetchingChannels = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
private void disableChannelSpinner() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, false);
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
}
|
||||||
|
private void enableChannelSpinner() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, true);
|
||||||
|
if (commentChannelSpinner != null) {
|
||||||
|
Claim selectedClaim = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
if (selectedClaim != null) {
|
||||||
|
if (selectedClaim.isPlaceholder()) {
|
||||||
|
showInlineChannelCreator();
|
||||||
|
} else {
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void showInlineChannelCreator() {
|
||||||
|
Helper.setViewVisibility(inlineChannelCreator, View.VISIBLE);
|
||||||
|
}
|
||||||
|
private void hideInlineChannelCreator() {
|
||||||
|
Helper.setViewVisibility(inlineChannelCreator, View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChannelList(List<Claim> channels) {
|
||||||
|
if (commentChannelSpinnerAdapter == null) {
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
commentChannelSpinnerAdapter = new InlineChannelSpinnerAdapter(context, R.layout.spinner_item_channel, new ArrayList<>(channels));
|
||||||
|
commentChannelSpinnerAdapter.addPlaceholder(false);
|
||||||
|
commentChannelSpinnerAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commentChannelSpinnerAdapter.clear();
|
||||||
|
commentChannelSpinnerAdapter.addAll(channels);
|
||||||
|
commentChannelSpinnerAdapter.addPlaceholder(false);
|
||||||
|
commentChannelSpinnerAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentChannelSpinner != null) {
|
||||||
|
commentChannelSpinner.setAdapter(commentChannelSpinnerAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentChannelSpinnerAdapter != null && commentChannelSpinner != null) {
|
||||||
|
if (commentChannelSpinnerAdapter.getCount() > 1) {
|
||||||
|
commentChannelSpinner.setSelection(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCommentForm(View root) {
|
||||||
|
double amount = Comment.COST / Lbryio.LBCUSDRate;
|
||||||
|
String buttonText = getResources().getQuantityString(R.plurals.post_for_credits, amount == 1 ? 1 : 2, Helper.LBC_CURRENCY_FORMAT.format(amount));
|
||||||
|
buttonPostComment.setText(buttonText);
|
||||||
|
textCommentLimit.setText(String.format("%d / %d", Helper.getValue(inputComment.getText()).length(), Comment.MAX_LENGTH));
|
||||||
|
|
||||||
|
buttonClearReplyToComment.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
clearReplyToComment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonPostComment.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (!Lbry.SDK_READY) {
|
||||||
|
Snackbar.make(root.findViewById(R.id.channel_comments_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateAndCheckPostComment(amount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
inputComment.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
int len = charSequence.length();
|
||||||
|
textCommentLimit.setText(String.format("%d / %d", len, Comment.MAX_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
commentChannelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
|
||||||
|
Object item = adapterView.getItemAtPosition(position);
|
||||||
|
if (item instanceof Claim) {
|
||||||
|
Claim claim = (Claim) item;
|
||||||
|
if (claim.isPlaceholder()) {
|
||||||
|
if (!fetchingChannels) {
|
||||||
|
showInlineChannelCreator();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
updatePostAsChannel(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAndCheckPostComment(double amount) {
|
||||||
|
String comment = Helper.getValue(inputComment.getText());
|
||||||
|
Claim channel = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
|
||||||
|
if (Helper.isNullOrEmpty(comment)) {
|
||||||
|
showError(getString(R.string.please_enter_comment));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (channel == null || Helper.isNullOrEmpty(channel.getClaimId())) {
|
||||||
|
showError(getString(R.string.please_select_channel));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Lbry.walletBalance == null || amount > Lbry.walletBalance.getAvailable().doubleValue()) {
|
||||||
|
showError(getString(R.string.insufficient_balance));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
String confirmText = getResources().getQuantityString(
|
||||||
|
R.plurals.confirm_post_comment,
|
||||||
|
amount == 1 ? 1 : 2,
|
||||||
|
Helper.LBC_CURRENCY_FORMAT.format(amount),
|
||||||
|
claim.getTitleOrName());
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context).
|
||||||
|
setTitle(R.string.post_comment).
|
||||||
|
setMessage(confirmText)
|
||||||
|
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
postComment(amount);
|
||||||
|
}
|
||||||
|
}).setNegativeButton(R.string.no, null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePostAsChannel(Claim channel) {
|
||||||
|
boolean hasThumbnail = !Helper.isNullOrEmpty(channel.getThumbnailUrl());
|
||||||
|
Helper.setViewVisibility(commentPostAsThumbnail, hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
Helper.setViewVisibility(commentPostAsNoThumbnail, !hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
Helper.setViewText(commentPostAsAlpha, channel.getName() != null ? channel.getName().substring(1, 2).toUpperCase() : null);
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
int bgColor = Helper.generateRandomColorForValue(channel.getClaimId());
|
||||||
|
Helper.setIconViewBackgroundColor(commentPostAsNoThumbnail, bgColor, false, context);
|
||||||
|
|
||||||
|
if (hasThumbnail && context != null) {
|
||||||
|
Glide.with(context.getApplicationContext()).
|
||||||
|
asBitmap().
|
||||||
|
load(channel.getThumbnailUrl()).
|
||||||
|
apply(RequestOptions.circleCropTransform()).
|
||||||
|
into(commentPostAsThumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void beforePostComment() {
|
||||||
|
postingComment = true;
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, false);
|
||||||
|
Helper.setViewEnabled(inputComment, false);
|
||||||
|
Helper.setViewEnabled(buttonClearReplyToComment, false);
|
||||||
|
Helper.setViewEnabled(buttonPostComment, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void afterPostComment() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, true);
|
||||||
|
Helper.setViewEnabled(inputComment, true);
|
||||||
|
Helper.setViewEnabled(buttonClearReplyToComment, true);
|
||||||
|
Helper.setViewEnabled(buttonPostComment, true);
|
||||||
|
postingComment = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Comment buildPostComment() {
|
||||||
|
Comment comment = new Comment();
|
||||||
|
Claim channel = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
comment.setClaimId(claim.getClaimId());
|
||||||
|
comment.setChannelId(channel.getClaimId());
|
||||||
|
comment.setChannelName(channel.getName());
|
||||||
|
comment.setText(Helper.getValue(inputComment.getText()));
|
||||||
|
comment.setPoster(channel);
|
||||||
|
if (replyToComment != null) {
|
||||||
|
comment.setParentId(replyToComment.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setReplyToComment(Comment comment) {
|
||||||
|
replyToComment = comment;
|
||||||
|
Helper.setViewText(textReplyingTo, getString(R.string.replying_to, comment.getChannelName()));
|
||||||
|
Helper.setViewText(textReplyToBody, comment.getText());
|
||||||
|
Helper.setViewVisibility(containerReplyToComment, View.VISIBLE);
|
||||||
|
|
||||||
|
inputComment.requestFocus();
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.showSoftInput(inputComment, InputMethodManager.SHOW_FORCED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearReplyToComment() {
|
||||||
|
Helper.setViewText(textReplyingTo, null);
|
||||||
|
Helper.setViewText(textReplyToBody, null);
|
||||||
|
Helper.setViewVisibility(containerReplyToComment, View.GONE);
|
||||||
|
replyToComment = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postComment(double tipAmount) {
|
||||||
|
if (postingComment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment comment = buildPostComment();
|
||||||
|
// only use 2 decimal places
|
||||||
|
BigDecimal amount = new BigDecimal(new DecimalFormat(Helper.PLAIN_CURRENCY_FORMAT_PATTERN).format(tipAmount));
|
||||||
|
|
||||||
|
beforePostComment();
|
||||||
|
CommentCreateWithTipTask task = new CommentCreateWithTipTask(comment, amount, progressPostComment, new CommentCreateWithTipTask.CommentCreateWithTipHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Comment createdComment) {
|
||||||
|
inputComment.setText(null);
|
||||||
|
clearReplyToComment();
|
||||||
|
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
createdComment.setPoster(comment.getPoster());
|
||||||
|
if (!Helper.isNullOrEmpty(createdComment.getParentId())) {
|
||||||
|
commentListAdapter.addReply(createdComment);
|
||||||
|
} else {
|
||||||
|
commentListAdapter.insert(0, createdComment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afterPostComment();
|
||||||
|
checkNoComments();
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).showMessage(R.string.comment_posted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
showError(error.getMessage());
|
||||||
|
afterPostComment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showError(String message) {
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).showError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNoComments() {
|
||||||
|
View root = getView();
|
||||||
|
if (root != null) {
|
||||||
|
Helper.setViewVisibility(root.findViewById(R.id.channel_no_comments),
|
||||||
|
commentListAdapter == null || commentListAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupInlineChannelCreator(
|
||||||
|
View container,
|
||||||
|
TextInputEditText inputChannelName,
|
||||||
|
TextInputEditText inputDeposit,
|
||||||
|
View inlineBalanceView,
|
||||||
|
TextView inlineBalanceValue,
|
||||||
|
View linkCancel,
|
||||||
|
MaterialButton buttonCreate,
|
||||||
|
View progressView,
|
||||||
|
AppCompatSpinner channelSpinner,
|
||||||
|
InlineChannelSpinnerAdapter channelSpinnerAdapter) {
|
||||||
|
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onFocusChange(View view, boolean hasFocus) {
|
||||||
|
Helper.setViewVisibility(inlineBalanceView, hasFocus ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
linkCancel.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Helper.setViewText(inputChannelName, null);
|
||||||
|
Helper.setViewText(inputDeposit, null);
|
||||||
|
Helper.setViewVisibility(container, View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonCreate.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
// validate deposit and channel name
|
||||||
|
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
|
||||||
|
Claim claimToSave = new Claim();
|
||||||
|
claimToSave.setName(channelNameString);
|
||||||
|
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
|
||||||
|
String depositString = Helper.getValue(inputDeposit.getText());
|
||||||
|
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
|
||||||
|
showError(getString(R.string.please_enter_channel_name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!LbryUri.isNameValid(channelName)) {
|
||||||
|
showError(getString(R.string.channel_name_invalid_characters));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Helper.channelExists(channelName)) {
|
||||||
|
showError(getString(R.string.channel_name_already_created));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double depositAmount = 0;
|
||||||
|
try {
|
||||||
|
depositAmount = Double.valueOf(depositString);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
// pass
|
||||||
|
showError(getString(R.string.please_enter_valid_deposit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depositAmount == 0) {
|
||||||
|
String error = getResources().getQuantityString(R.plurals.min_deposit_required, depositAmount == 1 ? 1 : 2, String.valueOf(Helper.MIN_DEPOSIT));
|
||||||
|
showError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Lbry.walletBalance == null || Lbry.walletBalance.getAvailable().doubleValue() < depositAmount) {
|
||||||
|
showError(getString(R.string.deposit_more_than_balance));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelCreateUpdateTask task = new ChannelCreateUpdateTask(
|
||||||
|
claimToSave, new BigDecimal(depositString), false, progressView, new ClaimResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void beforeStart() {
|
||||||
|
Helper.setViewEnabled(inputChannelName, false);
|
||||||
|
Helper.setViewEnabled(inputDeposit, false);
|
||||||
|
Helper.setViewEnabled(buttonCreate, false);
|
||||||
|
Helper.setViewEnabled(linkCancel, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Claim claimResult) {
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
LogPublishTask logPublishTask = new LogPublishTask(claimResult);
|
||||||
|
logPublishTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel created
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("claim_id", claimResult.getClaimId());
|
||||||
|
bundle.putString("claim_name", claimResult.getName());
|
||||||
|
LbryAnalytics.logEvent(LbryAnalytics.EVENT_CHANNEL_CREATE, bundle);
|
||||||
|
|
||||||
|
// add the claim to the channel list and set it as the selected item
|
||||||
|
if (channelSpinnerAdapter != null) {
|
||||||
|
channelSpinnerAdapter.add(claimResult);
|
||||||
|
}
|
||||||
|
if (channelSpinner != null && channelSpinnerAdapter != null) {
|
||||||
|
channelSpinner.setSelection(channelSpinnerAdapter.getCount() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.setViewEnabled(inputChannelName, true);
|
||||||
|
Helper.setViewEnabled(inputDeposit, true);
|
||||||
|
Helper.setViewEnabled(buttonCreate, true);
|
||||||
|
Helper.setViewEnabled(linkCancel, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
Helper.setViewEnabled(inputChannelName, true);
|
||||||
|
Helper.setViewEnabled(inputDeposit, true);
|
||||||
|
Helper.setViewEnabled(buttonCreate, true);
|
||||||
|
Helper.setViewEnabled(linkCancel, true);
|
||||||
|
showError(error.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Helper.setViewText(inlineBalanceValue, Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -377,13 +377,6 @@ public class ChannelFormFragment extends BaseFragment implements
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showError(String message) {
|
|
||||||
Context context = getContext();
|
|
||||||
if (context != null) {
|
|
||||||
Snackbar.make(getView(), message, Snackbar.LENGTH_LONG).setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkPermissionsAndLaunchFilePicker(boolean isCover) {
|
public void checkPermissionsAndLaunchFilePicker(boolean isCover) {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
if (MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) {
|
if (MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) {
|
||||||
|
|
|
@ -446,7 +446,11 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
|
||||||
new TabLayoutMediator(tabLayout, tabPager, new TabLayoutMediator.TabConfigurationStrategy() {
|
new TabLayoutMediator(tabLayout, tabPager, new TabLayoutMediator.TabConfigurationStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
|
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
|
||||||
tab.setText(position == 0 ? R.string.content : R.string.about);
|
switch (position) {
|
||||||
|
case 0: tab.setText(R.string.content); break;
|
||||||
|
case 1: tab.setText(R.string.about); break;
|
||||||
|
case 2: tab.setText(R.string.comments); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).attach();
|
}).attach();
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
|
@ -516,6 +520,13 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
|
||||||
// pass
|
// pass
|
||||||
}
|
}
|
||||||
return aboutFragment;
|
return aboutFragment;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
ChannelCommentsFragment commentsFragment = ChannelCommentsFragment.class.newInstance();
|
||||||
|
if (channelClaim != null) {
|
||||||
|
commentsFragment.setClaim(channelClaim);
|
||||||
|
}
|
||||||
|
return commentsFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -527,7 +538,7 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -20,10 +21,12 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.WebResourceRequest;
|
import android.webkit.WebResourceRequest;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
|
import android.widget.AdapterView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
@ -31,6 +34,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.AppCompatSpinner;
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
@ -40,6 +44,7 @@ import androidx.webkit.WebSettingsCompat;
|
||||||
import androidx.webkit.WebViewFeature;
|
import androidx.webkit.WebViewFeature;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.github.chrisbanes.photoview.PhotoView;
|
import com.github.chrisbanes.photoview.PhotoView;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.DefaultControlDispatcher;
|
import com.google.android.exoplayer2.DefaultControlDispatcher;
|
||||||
|
@ -64,6 +69,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||||
import com.google.android.flexbox.FlexboxLayoutManager;
|
import com.google.android.flexbox.FlexboxLayoutManager;
|
||||||
import com.google.android.material.button.MaterialButton;
|
import com.google.android.material.button.MaterialButton;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
import org.commonmark.node.Node;
|
import org.commonmark.node.Node;
|
||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
|
@ -90,6 +96,7 @@ import io.lbry.browser.MainActivity;
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
import io.lbry.browser.adapter.ClaimListAdapter;
|
import io.lbry.browser.adapter.ClaimListAdapter;
|
||||||
import io.lbry.browser.adapter.CommentListAdapter;
|
import io.lbry.browser.adapter.CommentListAdapter;
|
||||||
|
import io.lbry.browser.adapter.InlineChannelSpinnerAdapter;
|
||||||
import io.lbry.browser.adapter.TagListAdapter;
|
import io.lbry.browser.adapter.TagListAdapter;
|
||||||
import io.lbry.browser.dialog.RepostClaimDialogFragment;
|
import io.lbry.browser.dialog.RepostClaimDialogFragment;
|
||||||
import io.lbry.browser.dialog.SendTipDialogFragment;
|
import io.lbry.browser.dialog.SendTipDialogFragment;
|
||||||
|
@ -112,6 +119,7 @@ import io.lbry.browser.model.UrlSuggestion;
|
||||||
import io.lbry.browser.model.WalletBalance;
|
import io.lbry.browser.model.WalletBalance;
|
||||||
import io.lbry.browser.model.lbryinc.Reward;
|
import io.lbry.browser.model.lbryinc.Reward;
|
||||||
import io.lbry.browser.model.lbryinc.Subscription;
|
import io.lbry.browser.model.lbryinc.Subscription;
|
||||||
|
import io.lbry.browser.tasks.CommentCreateWithTipTask;
|
||||||
import io.lbry.browser.tasks.CommentListHandler;
|
import io.lbry.browser.tasks.CommentListHandler;
|
||||||
import io.lbry.browser.tasks.CommentListTask;
|
import io.lbry.browser.tasks.CommentListTask;
|
||||||
import io.lbry.browser.tasks.GenericTaskHandler;
|
import io.lbry.browser.tasks.GenericTaskHandler;
|
||||||
|
@ -121,6 +129,7 @@ import io.lbry.browser.tasks.SetSdkSettingTask;
|
||||||
import io.lbry.browser.tasks.claim.AbandonHandler;
|
import io.lbry.browser.tasks.claim.AbandonHandler;
|
||||||
import io.lbry.browser.tasks.claim.AbandonStreamTask;
|
import io.lbry.browser.tasks.claim.AbandonStreamTask;
|
||||||
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
|
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
|
||||||
|
import io.lbry.browser.tasks.claim.ClaimListTask;
|
||||||
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
|
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
|
||||||
import io.lbry.browser.tasks.claim.ResolveTask;
|
import io.lbry.browser.tasks.claim.ResolveTask;
|
||||||
import io.lbry.browser.tasks.file.DeleteFileTask;
|
import io.lbry.browser.tasks.file.DeleteFileTask;
|
||||||
|
@ -191,6 +200,34 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
private WebView webView;
|
private WebView webView;
|
||||||
private boolean webViewAdded;
|
private boolean webViewAdded;
|
||||||
|
|
||||||
|
private Comment replyToComment;
|
||||||
|
private View containerReplyToComment;
|
||||||
|
private TextView textReplyingTo;
|
||||||
|
private TextView textReplyToBody;
|
||||||
|
private View buttonClearReplyToComment;
|
||||||
|
|
||||||
|
private boolean postingComment;
|
||||||
|
private boolean fetchingChannels;
|
||||||
|
private View progressLoadingChannels;
|
||||||
|
private View progressPostComment;
|
||||||
|
private InlineChannelSpinnerAdapter commentChannelSpinnerAdapter;
|
||||||
|
private AppCompatSpinner commentChannelSpinner;
|
||||||
|
private TextInputEditText inputComment;
|
||||||
|
private TextView textCommentLimit;
|
||||||
|
private MaterialButton buttonPostComment;
|
||||||
|
private ImageView commentPostAsThumbnail;
|
||||||
|
private View commentPostAsNoThumbnail;
|
||||||
|
private TextView commentPostAsAlpha;
|
||||||
|
|
||||||
|
private View inlineChannelCreator;
|
||||||
|
private TextInputEditText inlineChannelCreatorInputName;
|
||||||
|
private TextInputEditText inlineChannelCreatorInputDeposit;
|
||||||
|
private View inlineChannelCreatorInlineBalance;
|
||||||
|
private TextView inlineChannelCreatorInlineBalanceValue;
|
||||||
|
private View inlineChannelCreatorCancelLink;
|
||||||
|
private View inlineChannelCreatorProgress;
|
||||||
|
private MaterialButton inlineChannelCreatorCreateButton;
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
View root = inflater.inflate(R.layout.fragment_file_view, container, false);
|
View root = inflater.inflate(R.layout.fragment_file_view, container, false);
|
||||||
|
@ -201,6 +238,30 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
layoutDisplayArea = root.findViewById(R.id.file_view_claim_display_area);
|
layoutDisplayArea = root.findViewById(R.id.file_view_claim_display_area);
|
||||||
buttonPublishSomething = root.findViewById(R.id.nothing_at_location_publish_button);
|
buttonPublishSomething = root.findViewById(R.id.nothing_at_location_publish_button);
|
||||||
|
|
||||||
|
containerReplyToComment = root.findViewById(R.id.comment_form_reply_to_container);
|
||||||
|
textReplyingTo = root.findViewById(R.id.comment_form_replying_to_text);
|
||||||
|
textReplyToBody = root.findViewById(R.id.comment_form_reply_to_body);
|
||||||
|
buttonClearReplyToComment = root.findViewById(R.id.comment_form_clear_reply_to);
|
||||||
|
|
||||||
|
commentChannelSpinner = root.findViewById(R.id.comment_form_channel_spinner);
|
||||||
|
progressLoadingChannels = root.findViewById(R.id.comment_form_channels_loading);
|
||||||
|
progressPostComment = root.findViewById(R.id.comment_form_post_progress);
|
||||||
|
inputComment = root.findViewById(R.id.comment_form_body);
|
||||||
|
textCommentLimit = root.findViewById(R.id.comment_form_text_limit);
|
||||||
|
buttonPostComment = root.findViewById(R.id.comment_form_post);
|
||||||
|
commentPostAsThumbnail = root.findViewById(R.id.comment_form_thumbnail);
|
||||||
|
commentPostAsNoThumbnail = root.findViewById(R.id.comment_form_no_thumbnail);
|
||||||
|
commentPostAsAlpha = root.findViewById(R.id.comment_form_thumbnail_alpha);
|
||||||
|
|
||||||
|
inlineChannelCreator = root.findViewById(R.id.container_inline_channel_form_create);
|
||||||
|
inlineChannelCreatorInputName = root.findViewById(R.id.inline_channel_form_input_name);
|
||||||
|
inlineChannelCreatorInputDeposit = root.findViewById(R.id.inline_channel_form_input_deposit);
|
||||||
|
inlineChannelCreatorInlineBalance = root.findViewById(R.id.inline_channel_form_inline_balance_container);
|
||||||
|
inlineChannelCreatorInlineBalanceValue = root.findViewById(R.id.inline_channel_form_inline_balance_value);
|
||||||
|
inlineChannelCreatorProgress = root.findViewById(R.id.inline_channel_form_create_progress);
|
||||||
|
inlineChannelCreatorCancelLink = root.findViewById(R.id.inline_channel_form_cancel_link);
|
||||||
|
inlineChannelCreatorCreateButton = root.findViewById(R.id.inline_channel_form_create_button);
|
||||||
|
|
||||||
initUi(root);
|
initUi(root);
|
||||||
|
|
||||||
fileViewPlayerListener = new Player.EventListener() {
|
fileViewPlayerListener = new Player.EventListener() {
|
||||||
|
@ -444,7 +505,14 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
|
|
||||||
View root = getView();
|
View root = getView();
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
|
if (relatedContentAdapter != null) {
|
||||||
|
relatedContentAdapter.clearItems();
|
||||||
|
}
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
commentListAdapter.clearItems();
|
||||||
|
}
|
||||||
((RecyclerView) root.findViewById(R.id.file_view_related_content_list)).setAdapter(null);
|
((RecyclerView) root.findViewById(R.id.file_view_related_content_list)).setAdapter(null);
|
||||||
|
((RecyclerView) root.findViewById(R.id.file_view_comments_list)).setAdapter(null);
|
||||||
}
|
}
|
||||||
if (MainActivity.appPlayer != null) {
|
if (MainActivity.appPlayer != null) {
|
||||||
MainActivity.appPlayer.setPlayWhenReady(false);
|
MainActivity.appPlayer.setPlayWhenReady(false);
|
||||||
|
@ -457,6 +525,7 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
loadFile();
|
loadFile();
|
||||||
}
|
}
|
||||||
checkOwnClaim();
|
checkOwnClaim();
|
||||||
|
fetchChannels();
|
||||||
checkAndLoadComments();
|
checkAndLoadComments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,6 +569,10 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
if (!claim.isPlayable() && !claim.isViewable()) {
|
if (!claim.isPlayable() && !claim.isViewable()) {
|
||||||
showUnsupportedView();
|
showUnsupportedView();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!claim.isPlayable() && !claim.isViewable()) {
|
||||||
|
restoreMainActionButton();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initialFileLoadDone = true;
|
initialFileLoadDone = true;
|
||||||
|
@ -586,6 +659,7 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
} else {
|
} else {
|
||||||
onSdkReady();
|
onSdkReady();
|
||||||
}
|
}
|
||||||
|
checkCommentSdkInitializing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
|
@ -1000,6 +1074,23 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
commentChannelSpinnerAdapter = new InlineChannelSpinnerAdapter(getContext(), R.layout.spinner_item_channel, new ArrayList<>());
|
||||||
|
commentChannelSpinnerAdapter.addPlaceholder(false);
|
||||||
|
|
||||||
|
initCommentForm(root);
|
||||||
|
setupInlineChannelCreator(
|
||||||
|
inlineChannelCreator,
|
||||||
|
inlineChannelCreatorInputName,
|
||||||
|
inlineChannelCreatorInputDeposit,
|
||||||
|
inlineChannelCreatorInlineBalance,
|
||||||
|
inlineChannelCreatorInlineBalanceValue,
|
||||||
|
inlineChannelCreatorCancelLink,
|
||||||
|
inlineChannelCreatorCreateButton,
|
||||||
|
inlineChannelCreatorProgress,
|
||||||
|
commentChannelSpinner,
|
||||||
|
commentChannelSpinnerAdapter
|
||||||
|
);
|
||||||
|
|
||||||
RecyclerView relatedContentList = root.findViewById(R.id.file_view_related_content_list);
|
RecyclerView relatedContentList = root.findViewById(R.id.file_view_related_content_list);
|
||||||
RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list);
|
RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list);
|
||||||
relatedContentList.setNestedScrollingEnabled(false);
|
relatedContentList.setNestedScrollingEnabled(false);
|
||||||
|
@ -1240,15 +1331,7 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
Claim.GenericMetadata metadata = claim.getValue();
|
Claim.GenericMetadata metadata = claim.getValue();
|
||||||
if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
|
if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
|
||||||
ImageView thumbnailView = root.findViewById(R.id.file_view_thumbnail);
|
ImageView thumbnailView = root.findViewById(R.id.file_view_thumbnail);
|
||||||
new Handler().postDelayed(new Runnable() {
|
Glide.with(context.getApplicationContext()).asBitmap().load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (claim != null && context != null && thumbnailView != null) {
|
|
||||||
Glide.with(context.getApplicationContext()).asBitmap().load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// display first x letters of claim name, with random background
|
// display first x letters of claim name, with random background
|
||||||
}
|
}
|
||||||
|
@ -1336,19 +1419,22 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
private void checkAndLoadComments() {
|
private void checkAndLoadComments() {
|
||||||
View root = getView();
|
View root = getView();
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
|
checkCommentSdkInitializing();
|
||||||
RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list);
|
RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list);
|
||||||
if (commentsList == null || commentsList.getAdapter() == null || commentsList.getAdapter().getItemCount() == 0) {
|
if (commentsList == null || commentsList.getAdapter() == null || commentsList.getAdapter().getItemCount() == 0) {
|
||||||
TextView commentsSDKInitializing = root.findViewById(R.id.file_view_comments_sdk_initializing);
|
loadComments();
|
||||||
if (Lbry.SDK_READY) {
|
|
||||||
Helper.setViewVisibility(commentsSDKInitializing, View.GONE);
|
|
||||||
loadComments();
|
|
||||||
} else {
|
|
||||||
Helper.setViewVisibility(commentsSDKInitializing, View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkCommentSdkInitializing() {
|
||||||
|
View root = getView();
|
||||||
|
if (root != null) {
|
||||||
|
TextView commentsSDKInitializing = root.findViewById(R.id.file_view_comments_sdk_initializing);
|
||||||
|
Helper.setViewVisibility(commentsSDKInitializing, Lbry.SDK_READY ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void showUnsupportedView() {
|
private void showUnsupportedView() {
|
||||||
View root = getView();
|
View root = getView();
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
|
@ -1892,32 +1978,80 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
View root = getView();
|
View root = getView();
|
||||||
ProgressBar relatedLoading = root.findViewById(R.id.file_view_comments_progress);
|
ProgressBar relatedLoading = root.findViewById(R.id.file_view_comments_progress);
|
||||||
if (claim != null && root != null) {
|
if (claim != null && root != null) {
|
||||||
CommentListTask relatedTask = new CommentListTask(1, 999, claim.getClaimId(), relatedLoading, new CommentListHandler() {
|
CommentListTask task = new CommentListTask(1, 500, claim.getClaimId(), relatedLoading, new CommentListHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Comment> comments) {
|
public void onSuccess(List<Comment> comments, boolean hasReachedEnd) {
|
||||||
Context ctx = getContext();
|
Context ctx = getContext();
|
||||||
if (ctx != null) {
|
View root = getView();
|
||||||
|
if (ctx != null && root != null) {
|
||||||
commentListAdapter = new CommentListAdapter(comments, ctx);
|
commentListAdapter = new CommentListAdapter(comments, ctx);
|
||||||
|
commentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() {
|
||||||
|
@Override
|
||||||
|
public void onClaimClicked(Claim claim) {
|
||||||
|
if (!Helper.isNullOrEmpty(claim.getName()) &&
|
||||||
|
claim.getName().startsWith("@") &&
|
||||||
|
ctx instanceof MainActivity) {
|
||||||
|
((MainActivity) ctx).openChannelClaim(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
commentListAdapter.setReplyListener(new CommentListAdapter.ReplyClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onReplyClicked(Comment comment) {
|
||||||
|
setReplyToComment(comment);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
View v = getView();
|
RecyclerView relatedContentList = root.findViewById(R.id.file_view_comments_list);
|
||||||
if (v != null) {
|
relatedContentList.setAdapter(commentListAdapter);
|
||||||
RecyclerView relatedContentList = root.findViewById(R.id.file_view_comments_list);
|
commentListAdapter.notifyDataSetChanged();
|
||||||
relatedContentList.setAdapter(commentListAdapter);
|
|
||||||
commentListAdapter.notifyDataSetChanged();
|
|
||||||
|
|
||||||
Helper.setViewVisibility(
|
checkNoComments();
|
||||||
v.findViewById(R.id.file_view_no_comments),
|
resolveCommentPosters();
|
||||||
commentListAdapter == null || commentListAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception error) {
|
public void onError(Exception error) {
|
||||||
|
// pass
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
relatedTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNoComments() {
|
||||||
|
View root = getView();
|
||||||
|
if (root != null) {
|
||||||
|
Helper.setViewVisibility(root.findViewById(R.id.file_view_no_comments),
|
||||||
|
commentListAdapter == null || commentListAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveCommentPosters() {
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
List<String> urlsToResolve = new ArrayList<>(commentListAdapter.getClaimUrlsToResolve());
|
||||||
|
if (urlsToResolve.size() > 0) {
|
||||||
|
ResolveTask task = new ResolveTask(urlsToResolve, Lbry.SDK_CONNECTION_STRING, null, new ClaimListResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Claim> claims) {
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
for (Claim claim : claims) {
|
||||||
|
if (claim.getClaimId() != null) {
|
||||||
|
commentListAdapter.updatePosterForComment(claim.getClaimId(), claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commentListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2336,6 +2470,9 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
|
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
|
||||||
|
if (walletBalance != null && inlineChannelCreatorInlineBalanceValue != null) {
|
||||||
|
inlineChannelCreatorInlineBalanceValue.setText(Helper.shortCurrencyFormat(walletBalance.getAvailable().doubleValue()));
|
||||||
|
}
|
||||||
checkRewardsDriver();
|
checkRewardsDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2457,4 +2594,296 @@ public class FileViewFragment extends BaseFragment implements
|
||||||
setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetchChannels() {
|
||||||
|
if (Lbry.ownChannels != null && Lbry.ownChannels.size() > 0) {
|
||||||
|
updateChannelList(Lbry.ownChannels);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchingChannels = true;
|
||||||
|
disableChannelSpinner();
|
||||||
|
ClaimListTask task = new ClaimListTask(Claim.TYPE_CHANNEL, progressLoadingChannels, new ClaimListResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<Claim> claims) {
|
||||||
|
Lbry.ownChannels = new ArrayList<>(claims);
|
||||||
|
updateChannelList(Lbry.ownChannels);
|
||||||
|
enableChannelSpinner();
|
||||||
|
fetchingChannels = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
enableChannelSpinner();
|
||||||
|
fetchingChannels = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
private void disableChannelSpinner() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, false);
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
}
|
||||||
|
private void enableChannelSpinner() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, true);
|
||||||
|
if (commentChannelSpinner != null) {
|
||||||
|
Claim selectedClaim = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
if (selectedClaim != null) {
|
||||||
|
if (selectedClaim.isPlaceholder()) {
|
||||||
|
showInlineChannelCreator();
|
||||||
|
} else {
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void showInlineChannelCreator() {
|
||||||
|
Helper.setViewVisibility(inlineChannelCreator, View.VISIBLE);
|
||||||
|
}
|
||||||
|
private void hideInlineChannelCreator() {
|
||||||
|
Helper.setViewVisibility(inlineChannelCreator, View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChannelList(List<Claim> channels) {
|
||||||
|
if (commentChannelSpinnerAdapter == null) {
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
commentChannelSpinnerAdapter = new InlineChannelSpinnerAdapter(context, R.layout.spinner_item_channel, new ArrayList<>(channels));
|
||||||
|
commentChannelSpinnerAdapter.addPlaceholder(false);
|
||||||
|
commentChannelSpinnerAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commentChannelSpinnerAdapter.clear();
|
||||||
|
commentChannelSpinnerAdapter.addAll(channels);
|
||||||
|
commentChannelSpinnerAdapter.addPlaceholder(false);
|
||||||
|
commentChannelSpinnerAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentChannelSpinner != null) {
|
||||||
|
commentChannelSpinner.setAdapter(commentChannelSpinnerAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentChannelSpinnerAdapter != null && commentChannelSpinner != null) {
|
||||||
|
if (commentChannelSpinnerAdapter.getCount() > 1) {
|
||||||
|
commentChannelSpinner.setSelection(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCommentForm(View root) {
|
||||||
|
double amount = Comment.COST / Lbryio.LBCUSDRate;
|
||||||
|
String buttonText = getResources().getQuantityString(R.plurals.post_for_credits, amount == 1 ? 1 : 2, Helper.LBC_CURRENCY_FORMAT.format(amount));
|
||||||
|
buttonPostComment.setText(buttonText);
|
||||||
|
textCommentLimit.setText(String.format("%d / %d", Helper.getValue(inputComment.getText()).length(), Comment.MAX_LENGTH));
|
||||||
|
|
||||||
|
buttonClearReplyToComment.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
clearReplyToComment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonPostComment.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (!Lbry.SDK_READY) {
|
||||||
|
Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validateAndCheckPostComment(amount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
inputComment.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
int len = charSequence.length();
|
||||||
|
textCommentLimit.setText(String.format("%d / %d", len, Comment.MAX_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
commentChannelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
|
||||||
|
Object item = adapterView.getItemAtPosition(position);
|
||||||
|
if (item instanceof Claim) {
|
||||||
|
Claim claim = (Claim) item;
|
||||||
|
if (claim.isPlaceholder()) {
|
||||||
|
if (!fetchingChannels) {
|
||||||
|
showInlineChannelCreator();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hideInlineChannelCreator();
|
||||||
|
updatePostAsChannel(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAndCheckPostComment(double amount) {
|
||||||
|
String comment = Helper.getValue(inputComment.getText());
|
||||||
|
Claim channel = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
|
||||||
|
if (Helper.isNullOrEmpty(comment)) {
|
||||||
|
showError(getString(R.string.please_enter_comment));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (channel == null || Helper.isNullOrEmpty(channel.getClaimId())) {
|
||||||
|
showError(getString(R.string.please_select_channel));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Lbry.walletBalance == null || amount > Lbry.walletBalance.getAvailable().doubleValue()) {
|
||||||
|
showError(getString(R.string.insufficient_balance));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
String confirmText = getResources().getQuantityString(
|
||||||
|
R.plurals.confirm_post_comment,
|
||||||
|
amount == 1 ? 1 : 2,
|
||||||
|
Helper.LBC_CURRENCY_FORMAT.format(amount),
|
||||||
|
claim.getTitleOrName());
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context).
|
||||||
|
setTitle(R.string.post_comment).
|
||||||
|
setMessage(confirmText)
|
||||||
|
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
postComment(amount);
|
||||||
|
}
|
||||||
|
}).setNegativeButton(R.string.no, null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePostAsChannel(Claim channel) {
|
||||||
|
boolean hasThumbnail = !Helper.isNullOrEmpty(channel.getThumbnailUrl());
|
||||||
|
Helper.setViewVisibility(commentPostAsThumbnail, hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
Helper.setViewVisibility(commentPostAsNoThumbnail, !hasThumbnail ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
Helper.setViewText(commentPostAsAlpha, channel.getName() != null ? channel.getName().substring(1, 2).toUpperCase() : null);
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
int bgColor = Helper.generateRandomColorForValue(channel.getClaimId());
|
||||||
|
Helper.setIconViewBackgroundColor(commentPostAsNoThumbnail, bgColor, false, context);
|
||||||
|
|
||||||
|
if (hasThumbnail && context != null) {
|
||||||
|
Glide.with(context.getApplicationContext()).
|
||||||
|
asBitmap().
|
||||||
|
load(channel.getThumbnailUrl()).
|
||||||
|
apply(RequestOptions.circleCropTransform()).
|
||||||
|
into(commentPostAsThumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void beforePostComment() {
|
||||||
|
postingComment = true;
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, false);
|
||||||
|
Helper.setViewEnabled(inputComment, false);
|
||||||
|
Helper.setViewEnabled(buttonClearReplyToComment, false);
|
||||||
|
Helper.setViewEnabled(buttonPostComment, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void afterPostComment() {
|
||||||
|
Helper.setViewEnabled(commentChannelSpinner, true);
|
||||||
|
Helper.setViewEnabled(inputComment, true);
|
||||||
|
Helper.setViewEnabled(buttonClearReplyToComment, true);
|
||||||
|
Helper.setViewEnabled(buttonPostComment, true);
|
||||||
|
postingComment = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Comment buildPostComment() {
|
||||||
|
Comment comment = new Comment();
|
||||||
|
Claim channel = (Claim) commentChannelSpinner.getSelectedItem();
|
||||||
|
comment.setClaimId(claim.getClaimId());
|
||||||
|
comment.setChannelId(channel.getClaimId());
|
||||||
|
comment.setChannelName(channel.getName());
|
||||||
|
comment.setText(Helper.getValue(inputComment.getText()));
|
||||||
|
comment.setPoster(channel);
|
||||||
|
if (replyToComment != null) {
|
||||||
|
comment.setParentId(replyToComment.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setReplyToComment(Comment comment) {
|
||||||
|
replyToComment = comment;
|
||||||
|
Helper.setViewText(textReplyingTo, getString(R.string.replying_to, comment.getChannelName()));
|
||||||
|
Helper.setViewText(textReplyToBody, comment.getText());
|
||||||
|
Helper.setViewVisibility(containerReplyToComment, View.VISIBLE);
|
||||||
|
|
||||||
|
inputComment.requestFocus();
|
||||||
|
Context context = getContext();
|
||||||
|
if (context != null) {
|
||||||
|
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.showSoftInput(inputComment, InputMethodManager.SHOW_FORCED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearReplyToComment() {
|
||||||
|
Helper.setViewText(textReplyingTo, null);
|
||||||
|
Helper.setViewText(textReplyToBody, null);
|
||||||
|
Helper.setViewVisibility(containerReplyToComment, View.GONE);
|
||||||
|
replyToComment = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postComment(double tipAmount) {
|
||||||
|
if (postingComment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Comment comment = buildPostComment();
|
||||||
|
// only use 2 decimal places
|
||||||
|
BigDecimal amount = new BigDecimal(new DecimalFormat(Helper.PLAIN_CURRENCY_FORMAT_PATTERN).format(tipAmount));
|
||||||
|
|
||||||
|
beforePostComment();
|
||||||
|
CommentCreateWithTipTask task = new CommentCreateWithTipTask(comment, amount, progressPostComment, new CommentCreateWithTipTask.CommentCreateWithTipHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Comment createdComment) {
|
||||||
|
inputComment.setText(null);
|
||||||
|
clearReplyToComment();
|
||||||
|
|
||||||
|
if (commentListAdapter != null) {
|
||||||
|
createdComment.setPoster(comment.getPoster());
|
||||||
|
if (!Helper.isNullOrEmpty(createdComment.getParentId())) {
|
||||||
|
commentListAdapter.addReply(createdComment);
|
||||||
|
} else {
|
||||||
|
commentListAdapter.insert(0, createdComment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
afterPostComment();
|
||||||
|
checkNoComments();
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
((MainActivity) context).showMessage(R.string.comment_posted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception error) {
|
||||||
|
showError(error.getMessage());
|
||||||
|
afterPostComment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,6 +475,8 @@ public class PublishFormFragment extends BaseFragment implements
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
channelSpinnerAdapter = new InlineChannelSpinnerAdapter(getContext(), R.layout.spinner_item_channel, new ArrayList<>());
|
||||||
|
channelSpinnerAdapter.addPlaceholder(false);
|
||||||
setupInlineChannelCreator(
|
setupInlineChannelCreator(
|
||||||
inlineChannelCreator,
|
inlineChannelCreator,
|
||||||
inlineChannelCreatorInputName,
|
inlineChannelCreatorInputName,
|
||||||
|
@ -483,7 +485,9 @@ public class PublishFormFragment extends BaseFragment implements
|
||||||
inlineChannelCreatorInlineBalanceValue,
|
inlineChannelCreatorInlineBalanceValue,
|
||||||
inlineChannelCreatorCancelLink,
|
inlineChannelCreatorCancelLink,
|
||||||
inlineChannelCreatorCreateButton,
|
inlineChannelCreatorCreateButton,
|
||||||
inlineChannelCreatorProgress
|
inlineChannelCreatorProgress,
|
||||||
|
channelSpinner,
|
||||||
|
channelSpinnerAdapter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,128 +1278,6 @@ public class PublishFormFragment extends BaseFragment implements
|
||||||
checkRewardsDriver();
|
checkRewardsDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupInlineChannelCreator(
|
|
||||||
View container,
|
|
||||||
TextInputEditText inputChannelName,
|
|
||||||
TextInputEditText inputDeposit,
|
|
||||||
View inlineBalanceView,
|
|
||||||
TextView inlineBalanceValue,
|
|
||||||
View linkCancel,
|
|
||||||
MaterialButton buttonCreate,
|
|
||||||
View progressView) {
|
|
||||||
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
Helper.setViewVisibility(inlineBalanceView, hasFocus ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
linkCancel.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Helper.setViewText(inputChannelName, null);
|
|
||||||
Helper.setViewText(inputDeposit, null);
|
|
||||||
Helper.setViewVisibility(container, View.GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonCreate.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
// validate deposit and channel name
|
|
||||||
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
|
|
||||||
Claim claimToSave = new Claim();
|
|
||||||
claimToSave.setName(channelNameString);
|
|
||||||
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
|
|
||||||
String depositString = Helper.getValue(inputDeposit.getText());
|
|
||||||
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
|
|
||||||
showError(getString(R.string.please_enter_channel_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!LbryUri.isNameValid(channelName)) {
|
|
||||||
showError(getString(R.string.channel_name_invalid_characters));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Helper.channelExists(channelName)) {
|
|
||||||
showError(getString(R.string.channel_name_already_created));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double depositAmount = 0;
|
|
||||||
try {
|
|
||||||
depositAmount = Double.valueOf(depositString);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
// pass
|
|
||||||
showError(getString(R.string.please_enter_valid_deposit));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (depositAmount == 0) {
|
|
||||||
String error = getResources().getQuantityString(R.plurals.min_deposit_required, depositAmount == 1 ? 1 : 2, String.valueOf(Helper.MIN_DEPOSIT));
|
|
||||||
showError(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Lbry.walletBalance == null || Lbry.walletBalance.getAvailable().doubleValue() < depositAmount) {
|
|
||||||
showError(getString(R.string.deposit_more_than_balance));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelCreateUpdateTask task = new ChannelCreateUpdateTask(
|
|
||||||
claimToSave, new BigDecimal(depositString), false, progressView, new ClaimResultHandler() {
|
|
||||||
@Override
|
|
||||||
public void beforeStart() {
|
|
||||||
Helper.setViewEnabled(inputChannelName, false);
|
|
||||||
Helper.setViewEnabled(inputDeposit, false);
|
|
||||||
Helper.setViewEnabled(buttonCreate, false);
|
|
||||||
Helper.setViewEnabled(linkCancel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Claim claimResult) {
|
|
||||||
if (!BuildConfig.DEBUG) {
|
|
||||||
LogPublishTask logPublishTask = new LogPublishTask(claimResult);
|
|
||||||
logPublishTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// channel created
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString("claim_id", claimResult.getClaimId());
|
|
||||||
bundle.putString("claim_name", claimResult.getName());
|
|
||||||
LbryAnalytics.logEvent(LbryAnalytics.EVENT_CHANNEL_CREATE, bundle);
|
|
||||||
|
|
||||||
// add the claim to the channel list and set it as the selected item
|
|
||||||
channelSpinnerAdapter.add(claimResult);
|
|
||||||
channelSpinner.setSelection(channelSpinnerAdapter.getCount() - 1);
|
|
||||||
|
|
||||||
Helper.setViewEnabled(inputChannelName, true);
|
|
||||||
Helper.setViewEnabled(inputDeposit, true);
|
|
||||||
Helper.setViewEnabled(buttonCreate, true);
|
|
||||||
Helper.setViewEnabled(linkCancel, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception error) {
|
|
||||||
Helper.setViewEnabled(inputChannelName, true);
|
|
||||||
Helper.setViewEnabled(inputDeposit, true);
|
|
||||||
Helper.setViewEnabled(buttonCreate, true);
|
|
||||||
Helper.setViewEnabled(linkCancel, true);
|
|
||||||
showError(error.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.setViewText(inlineBalanceValue, Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showError(String message) {
|
|
||||||
Context context = getContext();
|
|
||||||
if (context != null) {
|
|
||||||
Snackbar.make(getView(), message, Snackbar.LENGTH_LONG).
|
|
||||||
setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkUploadButton() {
|
private void checkUploadButton() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,6 +248,8 @@ public class InvitesFragment extends BaseFragment implements SdkStatusListener,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
channelSpinnerAdapter = new InlineChannelSpinnerAdapter(getContext(), R.layout.spinner_item_channel, new ArrayList<>());
|
||||||
|
channelSpinnerAdapter.addPlaceholder(false);
|
||||||
setupInlineChannelCreator(
|
setupInlineChannelCreator(
|
||||||
inlineChannelCreator,
|
inlineChannelCreator,
|
||||||
inlineChannelCreatorInputName,
|
inlineChannelCreatorInputName,
|
||||||
|
@ -256,7 +258,9 @@ public class InvitesFragment extends BaseFragment implements SdkStatusListener,
|
||||||
inlineChannelCreatorInlineBalanceValue,
|
inlineChannelCreatorInlineBalanceValue,
|
||||||
inlineChannelCreatorCancelLink,
|
inlineChannelCreatorCancelLink,
|
||||||
inlineChannelCreatorCreateButton,
|
inlineChannelCreatorCreateButton,
|
||||||
inlineChannelCreatorProgress
|
inlineChannelCreatorProgress,
|
||||||
|
channelSpinner,
|
||||||
|
channelSpinnerAdapter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,120 +459,6 @@ public class InvitesFragment extends BaseFragment implements SdkStatusListener,
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupInlineChannelCreator(
|
|
||||||
View container,
|
|
||||||
TextInputEditText inputChannelName,
|
|
||||||
TextInputEditText inputDeposit,
|
|
||||||
View inlineBalanceView,
|
|
||||||
TextView inlineBalanceValue,
|
|
||||||
View linkCancel,
|
|
||||||
MaterialButton buttonCreate,
|
|
||||||
View progressView) {
|
|
||||||
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
Helper.setViewVisibility(inlineBalanceView, hasFocus ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
linkCancel.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Helper.setViewText(inputChannelName, null);
|
|
||||||
Helper.setViewText(inputDeposit, null);
|
|
||||||
Helper.setViewVisibility(container, View.GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonCreate.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
// validate deposit and channel name
|
|
||||||
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
|
|
||||||
Claim claimToSave = new Claim();
|
|
||||||
claimToSave.setName(channelNameString);
|
|
||||||
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
|
|
||||||
String depositString = Helper.getValue(inputDeposit.getText());
|
|
||||||
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
|
|
||||||
showError(getString(R.string.please_enter_channel_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!LbryUri.isNameValid(channelName)) {
|
|
||||||
showError(getString(R.string.channel_name_invalid_characters));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Helper.channelExists(channelName)) {
|
|
||||||
showError(getString(R.string.channel_name_already_created));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double depositAmount = 0;
|
|
||||||
try {
|
|
||||||
depositAmount = Double.valueOf(depositString);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
// pass
|
|
||||||
showError(getString(R.string.please_enter_valid_deposit));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (depositAmount == 0) {
|
|
||||||
String error = getResources().getQuantityString(R.plurals.min_deposit_required, depositAmount == 1 ? 1 : 2, String.valueOf(Helper.MIN_DEPOSIT));
|
|
||||||
showError(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Lbry.walletBalance == null || Lbry.walletBalance.getAvailable().doubleValue() < depositAmount) {
|
|
||||||
showError(getString(R.string.deposit_more_than_balance));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelCreateUpdateTask task = new ChannelCreateUpdateTask(
|
|
||||||
claimToSave, new BigDecimal(depositString), false, progressView, new ClaimResultHandler() {
|
|
||||||
@Override
|
|
||||||
public void beforeStart() {
|
|
||||||
Helper.setViewEnabled(inputChannelName, false);
|
|
||||||
Helper.setViewEnabled(inputDeposit, false);
|
|
||||||
Helper.setViewEnabled(buttonCreate, false);
|
|
||||||
Helper.setViewEnabled(linkCancel, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Claim claimResult) {
|
|
||||||
if (!BuildConfig.DEBUG) {
|
|
||||||
LogPublishTask logPublishTask = new LogPublishTask(claimResult);
|
|
||||||
logPublishTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// channel created
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString("claim_id", claimResult.getClaimId());
|
|
||||||
bundle.putString("claim_name", claimResult.getName());
|
|
||||||
LbryAnalytics.logEvent(LbryAnalytics.EVENT_CHANNEL_CREATE, bundle);
|
|
||||||
|
|
||||||
// add the claim to the channel list and set it as the selected item
|
|
||||||
channelSpinnerAdapter.add(claimResult);
|
|
||||||
channelSpinner.setSelection(channelSpinnerAdapter.getCount() - 1);
|
|
||||||
|
|
||||||
Helper.setViewEnabled(inputChannelName, true);
|
|
||||||
Helper.setViewEnabled(inputDeposit, true);
|
|
||||||
Helper.setViewEnabled(buttonCreate, true);
|
|
||||||
Helper.setViewEnabled(linkCancel, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception error) {
|
|
||||||
Helper.setViewEnabled(inputChannelName, true);
|
|
||||||
Helper.setViewEnabled(inputDeposit, true);
|
|
||||||
Helper.setViewEnabled(buttonCreate, true);
|
|
||||||
Helper.setViewEnabled(linkCancel, true);
|
|
||||||
showError(error.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.setViewText(inlineBalanceValue, Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
|
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
|
||||||
if (walletBalance != null && inlineChannelCreatorInlineBalanceValue != null) {
|
if (walletBalance != null && inlineChannelCreatorInlineBalanceValue != null) {
|
||||||
|
@ -577,14 +467,6 @@ public class InvitesFragment extends BaseFragment implements SdkStatusListener,
|
||||||
checkRewardsDriver();
|
checkRewardsDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showError(String message) {
|
|
||||||
Context context = getContext();
|
|
||||||
if (context != null) {
|
|
||||||
Snackbar.make(getView(), message, Snackbar.LENGTH_LONG).
|
|
||||||
setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkRewardsDriver() {
|
private void checkRewardsDriver() {
|
||||||
Context ctx = getContext();
|
Context ctx = getContext();
|
||||||
View root = getView();
|
View root = getView();
|
||||||
|
|
|
@ -70,6 +70,7 @@ public final class Helper {
|
||||||
public static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
public static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
||||||
public static final int CONTENT_PAGE_SIZE = 25;
|
public static final int CONTENT_PAGE_SIZE = 25;
|
||||||
public static final double MIN_DEPOSIT = 0.001;
|
public static final double MIN_DEPOSIT = 0.001;
|
||||||
|
public static final String PLAIN_CURRENCY_FORMAT_PATTERN = "####.##";
|
||||||
public static final String LBC_CURRENCY_FORMAT_PATTERN = "#,###.##";
|
public static final String LBC_CURRENCY_FORMAT_PATTERN = "#,###.##";
|
||||||
public static final String FILE_SIZE_FORMAT_PATTERN = "#,###.#";
|
public static final String FILE_SIZE_FORMAT_PATTERN = "#,###.#";
|
||||||
public static final DecimalFormat LBC_CURRENCY_FORMAT = new DecimalFormat(LBC_CURRENCY_FORMAT_PATTERN);
|
public static final DecimalFormat LBC_CURRENCY_FORMAT = new DecimalFormat(LBC_CURRENCY_FORMAT_PATTERN);
|
||||||
|
|
|
@ -89,6 +89,8 @@ public final class Lbry {
|
||||||
public static final String METHOD_PREFERENCE_GET = "preference_get";
|
public static final String METHOD_PREFERENCE_GET = "preference_get";
|
||||||
public static final String METHOD_PREFERENCE_SET = "preference_set";
|
public static final String METHOD_PREFERENCE_SET = "preference_set";
|
||||||
|
|
||||||
|
public static final String METHOD_COMMENT_CREATE = "comment_create";
|
||||||
|
|
||||||
public static final String METHOD_TXO_LIST = "txo_list";
|
public static final String METHOD_TXO_LIST = "txo_list";
|
||||||
public static final String METHOD_TXO_SPEND = "txo_spend";
|
public static final String METHOD_TXO_SPEND = "txo_spend";
|
||||||
|
|
||||||
|
|
187
app/src/main/res/layout/container_comment_form.xml
Normal file
187
app/src/main/res/layout/container_comment_form.xml
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/comment_form_card"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:text="@string/post_as"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/comment_form_channels_loading"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatSpinner
|
||||||
|
android:id="@+id/comment_form_channel_spinner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp" />
|
||||||
|
|
||||||
|
<include layout="@layout/container_inline_channel_form" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/comment_form_reply_to_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
<View
|
||||||
|
android:id="@+id/comment_form_reply_to_vertical_bar"
|
||||||
|
android:layout_width="3dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@color/nextLbryGreen" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="8dp">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginRight="40dp">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_form_replying_to_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/replying_to"
|
||||||
|
android:textColor="@color/lightGrey"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_form_reply_to_body"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:lineSpacingMultiplier="1.05"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/comment_form_clear_reply_to"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_width="36dp"
|
||||||
|
android:layout_height="36dp">
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:src="@drawable/ic_close"
|
||||||
|
android:tint="@color/foreground" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/comment_form_avatar_container"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp">
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:background="@drawable/bg_channel_icon"
|
||||||
|
android:id="@+id/comment_form_no_thumbnail"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:visibility="invisible">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_form_thumbnail_alpha"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
</RelativeLayout>
|
||||||
|
<ImageView
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:id="@+id/comment_form_thumbnail"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toRightOf="@id/comment_form_avatar_container"
|
||||||
|
android:layout_marginLeft="16dp">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/comment_form_body"
|
||||||
|
android:hint="@string/comment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLength="2000"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_form_text_limit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textColor="@color/lightGrey"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/comment_form_post"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter" />
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/comment_form_post_progress"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toRightOf="@id/comment_form_post"
|
||||||
|
android:layout_marginLeft="24dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
|
@ -95,7 +95,9 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
app:tabGravity="center" />
|
android:paddingLeft="110dp"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
app:tabMode="scrollable"/>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/channel_view_icon_container"
|
android:id="@+id/channel_view_icon_container"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
|
|
71
app/src/main/res/layout/fragment_channel_comments.xml
Normal file
71
app/src/main/res/layout/fragment_channel_comments.xml
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp">
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/channel_comments_progress"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/channel_comments_area"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include layout="@layout/container_comment_form"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/channel_no_comments"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_comments"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/channel_comments_sdk_initializing"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/sdk_initializing_comments"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/channel_comments_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:overScrollMode="never" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
|
@ -37,7 +37,6 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/file_view_claim_display_area"
|
android:id="@+id/file_view_claim_display_area"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_weight="10"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
@ -45,8 +44,7 @@
|
||||||
android:id="@+id/file_view_media_container"
|
android:id="@+id/file_view_media_container"
|
||||||
android:background="@color/mediaContainerBackground"
|
android:background="@color/mediaContainerBackground"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="246dp">
|
||||||
android:layout_weight="3.55">
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/file_view_media_meta_container"
|
android:id="@+id/file_view_media_meta_container"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
|
@ -167,8 +165,7 @@
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
android:id="@+id/file_view_scroll_view"
|
android:id="@+id/file_view_scroll_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="6.45"
|
|
||||||
android:clipToPadding="false">
|
android:clipToPadding="false">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -571,7 +568,7 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/file_view_related_content_area"
|
android:id="@+id/file_view_related_content_area"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp">
|
android:layout_marginBottom="8dp">
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -590,7 +587,7 @@
|
||||||
android:id="@+id/file_view_related_content_progress"
|
android:id="@+id/file_view_related_content_progress"
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="16dp"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -623,7 +620,7 @@
|
||||||
android:id="@+id/file_view_comments_area"
|
android:id="@+id/file_view_comments_area"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="8dp"
|
android:paddingBottom="16dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -631,12 +628,11 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginRight="16dp">
|
android:layout_marginRight="16dp">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/file_view_comments_progress"
|
android:id="@+id/file_view_comments_progress"
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="16dp"
|
android:layout_height="16dp"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
@ -649,6 +645,8 @@
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/container_comment_form" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/file_view_no_comments"
|
android:id="@+id/file_view_no_comments"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -11,26 +11,96 @@
|
||||||
android:paddingRight="16dp"
|
android:paddingRight="16dp"
|
||||||
android:paddingTop="8dp">
|
android:paddingTop="8dp">
|
||||||
|
|
||||||
<LinearLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content">
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/comment_channel_name"
|
android:id="@+id/comment_avatar_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp">
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:background="@drawable/bg_channel_icon"
|
||||||
|
android:id="@+id/comment_no_thumbnail"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_thumbnail_alpha"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
</RelativeLayout>
|
||||||
|
<ImageView
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:id="@+id/comment_thumbnail"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/inter"
|
android:layout_toRightOf="@id/comment_avatar_container"
|
||||||
android:text="channel_name"
|
android:layout_marginLeft="16dp"
|
||||||
android:textColor="@color/lbryGreen"
|
android:orientation="vertical">
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/comment_text"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:layout_height="wrap_content"
|
<TextView
|
||||||
android:fontFamily="@font/inter"
|
android:id="@+id/comment_channel_name"
|
||||||
android:text="comment_text" />
|
android:background="?attr/selectableItemBackground"
|
||||||
</LinearLayout>
|
android:clickable="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textColor="@color/lbryGreen"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_time"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textColor="@color/lightGrey"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:lineSpacingMultiplier="1.1"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_reply_link"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/reply"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:textColor="@color/lbryGreen"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/comment_replies"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -60,8 +60,8 @@
|
||||||
<string name="loading_decentralized_data">Loading decentralized data...</string>
|
<string name="loading_decentralized_data">Loading decentralized data...</string>
|
||||||
<string name="related_content">Related Content</string>
|
<string name="related_content">Related Content</string>
|
||||||
<string name="comments">Comments</string>
|
<string name="comments">Comments</string>
|
||||||
<string name="no_comments">No comments to display.</string>
|
<string name="no_comments">No comments to display at this time.</string>
|
||||||
<string name="sdk_initializing_comments">Comments will display once the background service is done initializing.</string>
|
<string name="sdk_initializing_comments">Comments will display after the background service is initialized.</string>
|
||||||
<string name="share_lbry_content">Share LBRY content</string>
|
<string name="share_lbry_content">Share LBRY content</string>
|
||||||
<string name="view">View</string>
|
<string name="view">View</string>
|
||||||
<string name="play">Play</string>
|
<string name="play">Play</string>
|
||||||
|
@ -81,7 +81,23 @@
|
||||||
<string name="confirm_delete_content_message">Are you sure you want to unpublish this content? No files will be removed from your device.</string>
|
<string name="confirm_delete_content_message">Are you sure you want to unpublish this content? No files will be removed from your device.</string>
|
||||||
<string name="content_deleted">The content was successfully deleted from the blockchain.</string>
|
<string name="content_deleted">The content was successfully deleted from the blockchain.</string>
|
||||||
<string name="content_failed_delete">The content could not be deleted at this time. Please try again later.</string>
|
<string name="content_failed_delete">The content could not be deleted at this time. Please try again later.</string>
|
||||||
|
<string name="comment">Comment</string>
|
||||||
|
<string name="post_as">Post as</string>
|
||||||
|
<string name="please_enter_comment">Please enter a comment to post.</string>
|
||||||
|
<string name="please_select_channel">Please select a channel to post your comment as.</string>
|
||||||
|
<string name="post_comment">Post comment with tip?</string>
|
||||||
|
<string name="comment_posted">Your comment was successfully posted.</string>
|
||||||
<string name="please_select_repost_channel">Please select a channel to repost on.</string>
|
<string name="please_select_repost_channel">Please select a channel to repost on.</string>
|
||||||
|
<string name="reply">Reply</string>
|
||||||
|
<string name="replying_to">Replying to %1$s</string>
|
||||||
|
<plurals name="post_for_credits">
|
||||||
|
<item quantity="one">Post for %1$s credit</item>
|
||||||
|
<item quantity="other">Post for %1$s credits</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="confirm_post_comment">
|
||||||
|
<item quantity="one">This will post your comment with a tip of %1$s credit for %2$s</item>
|
||||||
|
<item quantity="other">This will post your comment with a tip of %1$s credits for %2$s</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="view_count">
|
<plurals name="view_count">
|
||||||
<item quantity="one">%1$s view</item>
|
<item quantity="one">%1$s view</item>
|
||||||
<item quantity="other">%1$s views</item>
|
<item quantity="other">%1$s views</item>
|
||||||
|
|
Loading…
Reference in a new issue