/**
* A row with and avatar, name and follow button
*
* The follow button switches between "Follow" and "Unfollow" depending on the follow status
* and provides and interface to know when the user has tried to follow or unfollow by tapping
* the button.
*
* Potentially can integrate with Gravatar using the avatar url to find profile JSON.
*/
package kr.kdev.dg1s.biowiki.ui.notifications;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.toolbox.NetworkImageView;
import org.json.JSONException;
import org.json.JSONObject;
import kr.kdev.dg1s.biowiki.R;
import kr.kdev.dg1s.biowiki.util.AniUtils;
import kr.kdev.dg1s.biowiki.util.AppLog;
import kr.kdev.dg1s.biowiki.util.HtmlUtils;
import kr.kdev.dg1s.biowiki.util.NetworkUtils;
public class FollowRow extends LinearLayout {
private static final String PARAMS_FIELD = "params";
private static final String TYPE_FIELD = "type";
private static final String ACTION_TYPE = "follow";
private static final String BLOG_ID_PARAM = "blog_id";
private static final String IS_FOLLOWING_PARAM = "is_following";
private static final String BLOG_URL_PARAM = "blog_url";
private static final String BLOG_DOMAIN_PARAM = "blog_domain";
private OnFollowListener mFollowListener;
private JSONObject mParams;
private String mBlogURL;
public FollowRow(Context context) {
super(context);
}
public FollowRow(Context context, AttributeSet attributes) {
super(context, attributes);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public FollowRow(Context context, AttributeSet attributes, int defStyle) {
super(context, attributes, defStyle);
}
void setAction(JSONObject actionJSON) {
final TextView followButton = getFollowButton();
getImageView().setDefaultImageResId(R.drawable.placeholder);
try {
if (actionJSON.has(TYPE_FIELD) && actionJSON.getString(TYPE_FIELD).equals(ACTION_TYPE)) {
// get the params for following
mParams = actionJSON.getJSONObject(PARAMS_FIELD);
// show the button
followButton.setVisibility(VISIBLE);
followButton.setOnClickListener(new ClickListener());
followButton.setOnLongClickListener(new LongClickListener());
setClickable(true);
} else {
mParams = null;
followButton.setVisibility(GONE);
followButton.setOnClickListener(null);
setClickable(false);
}
if (hasParams()) {
setSiteUrl(mParams.optString(BLOG_URL_PARAM, null));
} else {
setSiteUrl(null);
}
updateFollowButton(isFollowing());
} catch (JSONException e) {
AppLog.e(AppLog.T.NOTIFS, String.format("Could not set action from %s", actionJSON), e);
followButton.setVisibility(GONE);
setSiteUrl(null);
setClickable(false);
mParams = null;
}
}
private boolean hasParams() {
return mParams != null;
}
NetworkImageView getImageView() {
return (NetworkImageView) findViewById(R.id.avatar);
}
TextView getFollowButton() {
return (TextView) findViewById(R.id.text_follow);
}
TextView getNameTextView() {
return (TextView) findViewById(R.id.name);
}
TextView getSiteTextView() {
return (TextView) findViewById(R.id.url);
}
void setNameText(String text) {
TextView nameText = getNameTextView();
if (TextUtils.isEmpty(text)) {
nameText.setVisibility(View.GONE);
} else {
// text may contain html entities, so it must be unescaped for display
nameText.setText(HtmlUtils.fastUnescapeHtml(text));
nameText.setVisibility(View.VISIBLE);
}
}
boolean isSiteId(String siteId) {
String thisSiteId = getSiteId();
return (thisSiteId != null && thisSiteId.equals(siteId));
}
boolean isFollowing() {
return hasParams() && mParams.optBoolean(IS_FOLLOWING_PARAM, false);
}
void setFollowing(boolean following) {
if (hasParams()) {
try {
mParams.putOpt(IS_FOLLOWING_PARAM, following);
} catch (JSONException e) {
AppLog.e(AppLog.T.NOTIFS, String.format("Could not set following %b", following), e);
}
}
updateFollowButton(following);
}
String getSiteId() {
if (hasParams()) {
return mParams.optString(BLOG_ID_PARAM, null);
} else {
return null;
}
}
void setSiteUrl(String url) {
mBlogURL = url;
final TextView siteTextView = getSiteTextView();
if (!TextUtils.isEmpty(url)) {
siteTextView.setText(getSiteDomain());
siteTextView.setVisibility(View.VISIBLE);
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mBlogURL != null) {
NotificationsWebViewActivity.openUrl(getContext(), mBlogURL);
}
}
});
} else {
this.setOnClickListener(null);
siteTextView.setVisibility(View.GONE);
}
}
private String getSiteDomain() {
if (hasParams()) {
return mParams.optString(BLOG_DOMAIN_PARAM, null);
} else {
return null;
}
}
private OnFollowListener getFollowListener() {
return mFollowListener;
}
void setFollowListener(OnFollowListener listener) {
mFollowListener = listener;
}
private boolean hasFollowListener() {
return mFollowListener != null;
}
private void updateFollowButton(boolean isFollowing) {
final TextView followButton = getFollowButton();
int drawableId = (isFollowing ? R.drawable.note_icon_following : R.drawable.note_icon_follow);
followButton.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0);
followButton.setSelected(isFollowing);
followButton.setText(isFollowing ? R.string.reader_btn_unfollow : R.string.reader_btn_follow);
}
public static interface OnFollowListener {
public void onUnfollow(FollowRow row, String blogId);
public void onFollow(FollowRow row, String blogId);
}
private class ClickListener implements View.OnClickListener {
public void onClick(View v) {
if (!hasFollowListener()) {
return;
}
// first make sure we have a connection
if (!NetworkUtils.checkConnection(getContext()))
return;
// show new follow state and animate button right away (before network call)
updateFollowButton(!isFollowing());
AniUtils.zoomAction(getFollowButton());
if (isFollowing()) {
getFollowListener().onUnfollow(FollowRow.this, getSiteId());
} else {
getFollowListener().onFollow(FollowRow.this, getSiteId());
}
}
}
private class LongClickListener implements View.OnLongClickListener {
@Override
public boolean onLongClick(View v) {
Toast.makeText(getContext(), getResources().getString(R.string.tooltip_follow), Toast.LENGTH_SHORT).show();
return true;
}
}
}