/*
* Copyright (c) 2012 Socialize Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.socialize.ui.comment;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.socialize.Socialize;
import com.socialize.UserUtils;
import com.socialize.android.ioc.IBeanFactory;
import com.socialize.entity.Comment;
import com.socialize.entity.SocializeAction;
import com.socialize.entity.User;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.image.ImageLoader;
import com.socialize.ui.util.DateUtils;
import com.socialize.ui.view.CachedImageView;
import com.socialize.ui.view.ListItemLoadingView;
import com.socialize.util.CacheableDrawable;
import com.socialize.util.DisplayUtils;
import com.socialize.util.Drawables;
import com.socialize.util.StringUtils;
import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.List;
/**
* Provides comments to the comment view.
* @author Jason Polites
*/
public class CommentAdapter extends BaseAdapter {
private IBeanFactory<CommentListItem> commentItemViewFactory;
private IBeanFactory<ListItemLoadingView> listItemLoadingViewFactory;
private OnCommentViewActionListener onCommentViewActionListener;
private List<Comment> comments;
private SocializeLogger logger;
private Drawables drawables;
private View loadingView;
private DisplayUtils displayUtils;
private DateUtils dateUtils;
private ImageLoader imageLoader;
private WeakReference<Context> context;
private boolean last = false;
private Date now;
private int totalCount = 0;
private int count = 0;
private int viewCacheCount = 20;
private int viewCacheIndex = 0;
private int iconSize = 64;
private int densitySize = 64;
private final CommentListItem[] viewCache = new CommentListItem[viewCacheCount];
public void init(Context context) {
this.context = new WeakReference<Context>(context);
now = new Date();
if(displayUtils != null) {
densitySize = displayUtils.getDIP(iconSize);
}
if(commentItemViewFactory != null) {
for (int i = 0; i < viewCacheCount; i++) {
viewCache[i] = commentItemViewFactory.getBean();
}
}
viewCacheIndex = 0;
}
public void reset() {
if(comments != null) {
comments.clear();
}
last = false;
now = new Date();
viewCacheIndex = 0;
totalCount = 0;
count = 0;
notifyDataSetChanged();
notifyDataSetInvalidated();
}
@Override
public int getCount() {
return count;
}
public boolean isDisplayLoading() {
return !last && (comments != null && comments.size() > 0);
}
@Override
public Object getItem(int position) {
if(comments != null && position < comments.size()) {
return comments.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
if(!isDisplayLoading() || position < comments.size()) {
return 0;
}
else {
return 1;
}
}
@Override
public int getViewTypeCount() {
if(!isDisplayLoading()) {
return 1;
}
else {
return 2;
}
}
@Override
public View getView(final int position, View oldView, ViewGroup parent) {
View returnView = null;
CommentListItem view = null;
if(oldView instanceof CommentListItem) {
view = (CommentListItem) oldView;
}
User tmpUser = null;
final Comment item = (Comment) getItem(position);
if(item != null) {
tmpUser = item.getUser();
}
User currentUser = null;
if(Socialize.getSocialize().getSession() != null) {
currentUser = Socialize.getSocialize().getSession().getUser();
}
if(currentUser != null && tmpUser != null && currentUser.getId().equals(tmpUser.getId())) {
// Use this user as we may have been updated
tmpUser = currentUser;
}
final User user = tmpUser;
if (view == null) {
if(viewCacheIndex < viewCacheCount) {
view = viewCache[viewCacheIndex++];
}
else {
view = commentItemViewFactory.getBean();
}
}
if(view != null) {
view.setCommentObject(item);
view.setDeleteOk(false);
view.setOnClickListener(null);
view.setOnCreateContextMenuListener(null);
returnView = view;
if(position >= comments.size()) {
// Last one, get loading view
if(loadingView == null) {
loadingView = listItemLoadingViewFactory.getBean();
loadingView.setTag(null);
}
returnView = loadingView;
}
else {
if(item != null) {
String displayName;
String imageUrl = null;
if(user != null) {
imageUrl = user.getSmallImageUri();
displayName = user.getDisplayName();
if(displayName == null) {
// Use the item user
displayName = item.getUser().getDisplayName();
if(displayName == null) {
displayName = "Anonymous";
}
}
if(currentUser != null) {
view.setDeleteOk(user.getId().equals(currentUser.getId()));
}
final CommentListItem fItem = view;
view.getContentLayout().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(onCommentViewActionListener == null || !onCommentViewActionListener.onCommentItemClicked(fItem)) {
handleItemClick(user, item);
}
}
});
view.getIconLayout().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(onCommentViewActionListener == null || !onCommentViewActionListener.onCommentIconClicked(fItem)) {
handleItemClick(user, item);
}
}
});
}
else {
displayName = "Anonymous";
}
if(onCommentViewActionListener != null) {
onCommentViewActionListener.onBeforeSetComment(item, view);
}
TextView comment = view.getCommentText();
TextView userName = view.getAuthor();
TextView time = view.getTime();
ImageView locationIcon = view.getLocationIcon();
final CachedImageView userIcon = view.getUserIcon();
if (comment != null) {
comment.setText(item.getText());
}
if (userName != null) {
userName.setText(displayName);
}
if(locationIcon != null) {
if(item.hasLocation() && item.isLocationShared()) {
locationIcon.setVisibility(View.VISIBLE);
}
else {
locationIcon.setVisibility(View.GONE);
}
}
if (time != null) {
Long date = item.getDate();
if(date != null && date > 0) {
long diff = (now.getTime() - date);
time.setText(dateUtils.getTimeString(diff) + " ");
}
else {
time.setText(" ");
}
}
if (userIcon != null && drawables != null) {
if(user != null) {
// NPE on some devices (?)
if(userIcon.getBackground() != null) {
userIcon.getBackground().setAlpha(255);
}
if(!StringUtils.isEmpty(imageUrl)) {
try {
// Check the cache
CacheableDrawable cached = drawables.getCache().get(imageUrl);
if(cached != null && !cached.isRecycled()) {
if(logger != null && logger.isDebugEnabled()) {
logger.debug("CommentAdpater setting image icon to cached image " + cached);
}
userIcon.setExpectedImageName(imageUrl);
userIcon.setImageUrlImmediate(imageUrl, false);
}
else {
userIcon.setExpectedImageName(imageUrl);
userIcon.setDefaultImage();
imageLoader.loadImageByUrl(imageUrl, densitySize, densitySize, userIcon);
}
}
catch (Exception e) {
String errorMsg = "Not a valid image uri [" + imageUrl + "]";
logError(errorMsg, e);
userIcon.setExpectedImageName(Socialize.DEFAULT_USER_ICON);
userIcon.setDefaultImage();
}
}
else if(!StringUtils.isEmpty(user.getProfilePicData())) {
userIcon.setDefaultImage();
userIcon.setExpectedImageName("user_" + user.getId());
imageLoader.loadImageByData("user_" + user.getId(), user.getProfilePicData(), densitySize, densitySize, userIcon);
}
else {
userIcon.setExpectedImageName(Socialize.DEFAULT_USER_ICON);
userIcon.setDefaultImage();
}
}
}
if(onCommentViewActionListener != null) {
onCommentViewActionListener.onAfterSetComment(item, view);
}
}
}
}
if(returnView == null) {
returnView = oldView;
}
return returnView;
}
private void handleItemClick(User user, SocializeAction item) {
if (user != null && user.getId() != null) {
Context ctx = context.get();
if (ctx instanceof Activity) {
UserUtils.showUserProfileWithAction((Activity) ctx, user, item);
}
} else {
if (logger != null) {
logger.warn("No user for comment " + item.getId());
}
}
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
int extra = 0;
if(isDisplayLoading()) {
extra = 1;
}
count = (comments == null) ? 0 : comments.size() + extra;
}
public void setCommentItemViewFactory(IBeanFactory<CommentListItem> commentItemViewFactory) {
this.commentItemViewFactory = commentItemViewFactory;
}
public void setListItemLoadingViewFactory(IBeanFactory<ListItemLoadingView> listItemLoadingViewFactory) {
this.listItemLoadingViewFactory = listItemLoadingViewFactory;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
public void setLogger(SocializeLogger logger) {
this.logger = logger;
}
public void setLoadingView(View loadingView) {
this.loadingView = loadingView;
}
public boolean isLast() {
return last;
}
public void setLast(boolean last) {
this.last = last;
}
public void setDrawables(Drawables drawables) {
this.drawables = drawables;
}
public void setDisplayUtils(DisplayUtils deviceUtils) {
this.displayUtils = deviceUtils;
}
public void setDateUtils(DateUtils dateUtils) {
this.dateUtils = dateUtils;
}
public void setIconSize(int iconSize) {
this.iconSize = iconSize;
}
public void setImageLoader(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public OnCommentViewActionListener getOnCommentViewActionListener() {
return onCommentViewActionListener;
}
public void setOnCommentViewActionListener(OnCommentViewActionListener onCommentViewActionListener) {
this.onCommentViewActionListener = onCommentViewActionListener;
}
protected void logError(String msg, Exception e) {
if(logger != null) {
logger.error(msg, e);
}
else {
SocializeLogger.e(e.getMessage(), e);
}
}
}