/* * Copyright 2011 Azwan Adli Abdullah * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gh4a.adapter; import android.content.Context; import android.content.Intent; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.gh4a.Gh4Application; import com.gh4a.R; import com.gh4a.activities.UserActivity; import com.gh4a.utils.ApiHelpers; import com.gh4a.utils.AvatarHandler; import com.gh4a.utils.HttpImageGetter; import com.gh4a.utils.StringUtils; import com.gh4a.utils.UiUtils; import com.gh4a.widget.StyleableTextView; import org.eclipse.egit.github.core.User; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Set; abstract class CommentAdapterBase<T> extends RootAdapter<T, CommentAdapterBase.ViewHolder> { public interface OnCommentAction<T> { void editComment(T comment); void deleteComment(T comment); void quoteText(CharSequence text); } private final ViewHolder.OnCommentMenuItemClick<T> mCommentMenuItemClickCallback = new ViewHolder.OnCommentMenuItemClick<T>() { @Override public boolean onCommentMenuItemClick(T item, MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.edit: mActionCallback.editComment(item); return true; case R.id.delete: mActionCallback.deleteComment(item); return true; case R.id.share: Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(Intent.EXTRA_SUBJECT, getShareSubject(item)); shareIntent.putExtra(Intent.EXTRA_TEXT, getUrl(item)); shareIntent = Intent.createChooser(shareIntent, mContext.getString(R.string.share_title)); mContext.startActivity(shareIntent); return true; } return false; } }; private final HttpImageGetter mImageGetter; private final OnCommentAction mActionCallback; protected final String mRepoOwner; protected final String mRepoName; private boolean mDontClearCacheOnClear; protected CommentAdapterBase(Context context, String repoOwner, String repoName, OnCommentAction actionCallback) { super(context); mImageGetter = new HttpImageGetter(context); mRepoOwner = repoOwner; mRepoName = repoName; mActionCallback = actionCallback; } public void destroy() { mImageGetter.destroy(); } @Override public ViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) { View v = inflater.inflate(R.layout.row_gravatar_comment, parent, false); ViewHolder holder = new ViewHolder(v, mCommentMenuItemClickCallback); holder.ivGravatar.setOnClickListener(this); return holder; } @Override public void onBindViewHolder(ViewHolder holder, T item) { User user = getUser(item); Date createdAt = getCreatedAt(item); Date updatedAt = getUpdatedAt(item); AvatarHandler.assignAvatar(holder.ivGravatar, user); holder.ivGravatar.setTag(user); holder.tvTimestamp.setText(StringUtils.formatRelativeTime(mContext, createdAt, true)); if (createdAt.equals(updatedAt)) { holder.tvEditTimestamp.setVisibility(View.GONE); } else { holder.tvEditTimestamp.setText(StringUtils.formatRelativeTime(mContext, updatedAt, true)); holder.tvEditTimestamp.setVisibility(View.VISIBLE); } bindBodyView(item, holder.tvDesc, mImageGetter); bindExtraView(item, holder.tvExtra); bindFileView(item, holder.tvFile); bindEventIcon(item, holder.ivEventIcon); if (canQuote(item)) { holder.tvDesc.setCustomSelectionActionModeCallback( new UiUtils.QuoteActionModeCallback(holder.tvDesc) { @Override public void onTextQuoted(CharSequence text) { mActionCallback.quoteText(text); } }); } else { holder.tvDesc.setCustomSelectionActionModeCallback(null); } if (hasActionMenu(item)) { holder.ivMenu.setTag(item); holder.ivMenu.setVisibility(View.VISIBLE); } else { holder.ivMenu.setVisibility(View.GONE); } String ourLogin = Gh4Application.get().getAuthLogin(); boolean canEdit = ApiHelpers.loginEquals(user, ourLogin) || ApiHelpers.loginEquals(mRepoOwner, ourLogin); MenuItem editMenuItem = holder.mPopupMenu.getMenu().findItem(R.id.edit); MenuItem deleteMenuItem = holder.mPopupMenu.getMenu().findItem(R.id.delete); editMenuItem.setVisible(mActionCallback != null && canEdit); deleteMenuItem.setVisible(mActionCallback != null && canEdit); } public void resume() { mImageGetter.resume(); } public void pause() { mImageGetter.pause(); } public Set<User> getUsers() { final HashSet<User> users = new HashSet<>(); for (int i = 0; i < getCount(); i++) { final User user = getUser(getItem(i)); if (user != null) { users.add(user); } } return users; } public void suppressCacheClearOnNextClear() { mDontClearCacheOnClear = true; } @Override public void clear() { super.clear(); if (!mDontClearCacheOnClear) { mImageGetter.clearHtmlCache(); } } @Override public void addAll(Collection<T> objects) { mDontClearCacheOnClear = false; super.addAll(objects); } @Override public void onClick(View v) { if (v.getId() == R.id.iv_gravatar) { User user = (User) v.getTag(); Intent intent = UserActivity.makeIntent(mContext, user); if (intent != null) { mContext.startActivity(intent); } } else { super.onClick(v); } } protected abstract User getUser(T item); protected abstract Date getCreatedAt(T item); protected abstract Date getUpdatedAt(T item); protected abstract String getUrl(T item); protected abstract String getShareSubject(T item); protected abstract void bindBodyView(T item, StyleableTextView view, HttpImageGetter imageGetter); protected abstract void bindExtraView(T item, StyleableTextView view); protected abstract void bindFileView(T item, StyleableTextView view); protected abstract void bindEventIcon(T item, ImageView view); protected abstract boolean hasActionMenu(T item); protected abstract boolean canQuote(T item); public static class ViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener, PopupMenu.OnMenuItemClickListener { private interface OnCommentMenuItemClick<T> { boolean onCommentMenuItemClick(T comment, MenuItem item); } private ViewHolder(View view, OnCommentMenuItemClick commentMenuItemClickCallback) { super(view); mCommentMenuItemClickCallback = commentMenuItemClickCallback; ivGravatar = (ImageView) view.findViewById(R.id.iv_gravatar); ivEventIcon = (ImageView) view.findViewById(R.id.iv_event_icon); tvDesc = (StyleableTextView) view.findViewById(R.id.tv_desc); tvDesc.setMovementMethod(UiUtils.CHECKING_LINK_METHOD); tvExtra = (StyleableTextView) view.findViewById(R.id.tv_extra); tvTimestamp = (TextView) view.findViewById(R.id.tv_timestamp); tvEditTimestamp = (TextView) view.findViewById(R.id.tv_edit_timestamp); tvFile = (StyleableTextView) view.findViewById(R.id.tv_file); ivMenu = (ImageView) view.findViewById(R.id.iv_menu); ivMenu.setOnClickListener(this); mPopupMenu = new PopupMenu(view.getContext(), ivMenu); mPopupMenu.getMenuInflater().inflate(R.menu.comment_menu, mPopupMenu.getMenu()); mPopupMenu.setOnMenuItemClickListener(this); } private final ImageView ivGravatar; private final ImageView ivEventIcon; private final StyleableTextView tvDesc; private final StyleableTextView tvExtra; private final TextView tvTimestamp; private final TextView tvEditTimestamp; private final StyleableTextView tvFile; private final ImageView ivMenu; private final PopupMenu mPopupMenu; private final OnCommentMenuItemClick mCommentMenuItemClickCallback; @Override public void onClick(View v) { if (v.getId() == R.id.iv_menu) { mPopupMenu.show(); } } @Override public boolean onMenuItemClick(MenuItem menuItem) { T item = (T) ivMenu.getTag(); return mCommentMenuItemClickCallback.onCommentMenuItemClick(item, menuItem); } } }