/* * 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.actionbar; import android.app.Activity; import android.app.Dialog; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.widget.Toast; import com.socialize.CommentUtils; import com.socialize.EntityUtils; import com.socialize.LikeUtils; import com.socialize.ShareUtils; import com.socialize.ViewUtils; import com.socialize.android.ioc.IBeanFactory; import com.socialize.api.action.comment.CommentUtilsProxy; import com.socialize.api.action.share.ShareUtilsProxy; import com.socialize.api.action.share.SocialNetworkDialogListener; import com.socialize.entity.Entity; import com.socialize.entity.EntityStats; import com.socialize.entity.Like; import com.socialize.entity.View; import com.socialize.error.SocializeApiError; import com.socialize.error.SocializeException; import com.socialize.i18n.I18NConstants; import com.socialize.i18n.LocalizationService; import com.socialize.listener.entity.EntityGetListener; import com.socialize.listener.like.LikeAddListener; import com.socialize.listener.like.LikeDeleteListener; import com.socialize.listener.like.LikeGetListener; import com.socialize.listener.view.ViewAddListener; import com.socialize.log.SocializeLogger; import com.socialize.networks.SocialNetwork; import com.socialize.ui.actionbar.OnActionBarEventListener.ActionBarEvent; import com.socialize.ui.cache.CacheableEntity; import com.socialize.ui.cache.EntityCache; import com.socialize.ui.comment.OnCommentViewActionListener; import com.socialize.ui.dialog.ProgressDialogFactory; import com.socialize.ui.util.CompatUtils; import com.socialize.util.DisplayUtils; import com.socialize.util.Drawables; import com.socialize.view.BaseView; import org.json.JSONObject; import java.text.DecimalFormat; import java.text.NumberFormat; /** * @author Jason Polites */ public class ActionBarLayoutView extends BaseView { static final NumberFormat countFormat = new DecimalFormat("##0.0K"); private LocalizationService localizationService; private ActionBarButton commentButton; private ActionBarButton likeButton; private ActionBarButton shareButton; private ActionBarTicker ticker; private ActionBarItem viewsItem; private ActionBarItem commentsItem; private ActionBarItem likesItem; private ActionBarItem sharesItem; private Drawables drawables; private EntityCache entityCache; private SocializeLogger logger; private Drawable likeIcon; private Drawable likeIconHi; private Drawable commentIcon; private Drawable viewIcon; private Drawable shareIcon; private IBeanFactory<ActionBarButton> buttonFactory; private IBeanFactory<ActionBarTicker> tickerFactory; private IBeanFactory<ActionBarItem> itemFactory; private ProgressDialogFactory progressDialogFactory; private DisplayUtils displayUtils; private ShareUtilsProxy shareUtils; private CommentUtilsProxy commentUtils; private ActionBarView actionBarView; private ActionBarOptions options; final String loadingText = "..."; private OnActionBarEventListener onActionBarEventListener; private OnCommentViewActionListener onCommentViewActionListener; public ActionBarLayoutView(Activity context, ActionBarView actionBarView) { this(context, actionBarView, new ActionBarOptions()); } public ActionBarLayoutView(Activity context, ActionBarView actionBarView, ActionBarOptions options) { super(context); this.actionBarView = actionBarView; this.options = options; } private Drawable getIcon(Integer resourceId, String defaultName) { return (resourceId == null) ? drawables.getDrawable(defaultName) : getContext().getResources().getDrawable(resourceId); } public void init() { if(logger != null && logger.isDebugEnabled()) { logger.debug("init called on " + ((Object)this).getClass().getSimpleName()); } int height = ActionBarView.ACTION_BAR_HEIGHT; if(displayUtils != null) { height = displayUtils.getDIP(ActionBarView.ACTION_BAR_HEIGHT); } LayoutParams masterParams = new LayoutParams(LayoutParams.FILL_PARENT, height); masterParams.gravity = options.getGravity() | Gravity.CENTER_VERTICAL; setLayoutParams(masterParams); setGravity(options.getGravity()); if(!options.isHideLike() || !options.isHideTicker()) { likeIcon = getIcon(options.getLikeIconResourceId(), "icon_like.png"); likeIconHi = getIcon(options.getLikeIconActiveResourceId(), "icon_like_hi.png"); } if(!options.isHideComment() || !options.isHideTicker()) { commentIcon = getIcon(options.getCommentIconResourceId(), "icon_comment.png"); } if(!options.isHideShare() || !options.isHideTicker()) { shareIcon = getIcon(options.getShareIconResourceId(), "icon_share.png"); } if(!options.isHideTicker()) { viewIcon = getIcon(options.getViewIconResourceId(), "icon_view.png"); } int accentHeight = displayUtils.getDIP(4); int strokeWidth = displayUtils.getDIP(1); int width = ActionBarView.ACTION_BAR_BUTTON_WIDTH; int likeWidth = width - 5; int commentWidth = width + 15; int shareWidth = width- 5; if(!options.isHideTicker()) { ticker = tickerFactory.getBean(options.getBackgroundColor()); } int textColor = Color.WHITE; if(options.getTextColor() != null) { textColor = options.getTextColor(); } if(!options.isHideComment() || !options.isHideTicker()) { commentsItem = itemFactory.getBean(textColor); commentsItem.setIcon(commentIcon); if(!options.isHideComment()) commentButton = buttonFactory.getBean(); } if(!options.isHideLike() || !options.isHideTicker()) { likesItem = itemFactory.getBean(textColor); likesItem.setIcon(likeIcon); if(!options.isHideLike()) likeButton = buttonFactory.getBean(); } if(!options.isHideShare() || !options.isHideTicker()) { sharesItem = itemFactory.getBean(textColor); sharesItem.setIcon(shareIcon); if(!options.isHideShare()) shareButton = buttonFactory.getBean(); } if(!options.isHideTicker()) { viewsItem = itemFactory.getBean(textColor); viewsItem.setIcon(viewIcon); ticker.addTickerView(viewsItem); ticker.addTickerView(commentsItem); ticker.addTickerView(likesItem); ticker.addTickerView(sharesItem); } ActionBarButtonBackground bg = new ActionBarButtonBackground( accentHeight, strokeWidth, options.getStrokeColor(), options.getAccentColor(), options.getFillColor(), options.getHighlightColor(), options.getColorLayout()); if(commentButton != null) { commentButton.setIcon(commentIcon); CompatUtils.setBackgroundDrawable(commentButton, bg); commentButton.setListener(new ActionBarButtonListener() { @Override public void onClick(ActionBarButton button) { boolean consumed = false; if(onActionBarEventListener != null) { consumed = onActionBarEventListener.onClick(actionBarView, ActionBarEvent.COMMENT); } if(!consumed) { commentUtils.showCommentView(getActivity(), actionBarView.getEntity(), onCommentViewActionListener); } } }); } if(likeButton != null) { likeButton.setIcon(likeIcon); CompatUtils.setBackgroundDrawable(likeButton, bg); likeButton.setListener(new ActionBarButtonListener() { @Override public void onClick(ActionBarButton button) { boolean consumed = false; if(onActionBarEventListener != null) { consumed = onActionBarEventListener.onClick(actionBarView, ActionBarEvent.LIKE); } if(!consumed) { doLike(likeButton, null); } } }); } if(shareButton != null) { shareButton.setIcon(shareIcon); CompatUtils.setBackgroundDrawable(shareButton, bg); shareButton.setListener(new ActionBarButtonListener() { @Override public void onClick(ActionBarButton button) { boolean consumed = false; SocialNetworkDialogListener snListener = null; if(onActionBarEventListener != null) { consumed = onActionBarEventListener.onClick(actionBarView, ActionBarEvent.SHARE); if(onActionBarEventListener instanceof SocialNetworkDialogListener) { snListener = (SocialNetworkDialogListener) onActionBarEventListener; } } if(!consumed) { if(snListener == null) { snListener = new SocialNetworkDialogListener() { @Override public void onError(SocializeException error) { Toast.makeText(getActivity(), localizationService.getString(I18NConstants.ACTIONBAR_SHARE_FAIL), Toast.LENGTH_SHORT).show(); } @Override public void onNetworkError(Activity context, SocialNetwork network, Exception error) { Toast.makeText(context, localizationService.getString(I18NConstants.ACTIONBAR_SHARE_FAIL), Toast.LENGTH_SHORT).show(); } @Override public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) { Toast.makeText(parent, localizationService.getString(I18NConstants.ACTIONBAR_SHARE_SUCCESS), Toast.LENGTH_SHORT).show(); } @Override public void onCancel(Dialog dialog) { dialog.dismiss(); } }; } ShareUtils.showShareDialog(getActivity(), actionBarView.getEntity(), snListener); } } }); } if(ticker != null) { ticker.setOnClickListener(new OnClickListener() { @Override public void onClick(android.view.View v) { boolean consumed = false; if(onActionBarEventListener != null) { consumed = onActionBarEventListener.onClick(actionBarView, ActionBarEvent.VIEW); } if(!consumed) { ticker.skipToNext(); } } }); } if(viewsItem != null) { viewsItem.init(); viewsItem.setText(loadingText); } if(commentsItem != null) { commentsItem.init(); commentsItem.setText(loadingText); if(commentButton != null) { commentButton.init(commentWidth, 0.0f, textColor); commentButton.setText(localizationService.getString(I18NConstants.ACTIONBAR_COMMENT)); } } if(likesItem != null) { likesItem.init(); likesItem.setText(loadingText); if(likeButton != null) { likeButton.init(likeWidth, 0.0f, textColor); likeButton.setText(loadingText); } } if(sharesItem != null) { sharesItem.init(); sharesItem.setText(loadingText); if(shareButton != null) { shareButton.init(shareWidth, 0.0f, textColor); shareButton.setText(localizationService.getString(I18NConstants.ACTIONBAR_SHARE)); } } if(ticker != null) { ticker.init(LayoutParams.FILL_PARENT, 1.0f); } if(ticker != null) addView(ticker); if(likeButton != null) addView(likeButton); if(shareButton != null) addView(shareButton); if(commentButton != null) addView(commentButton); } @Override public void onViewLoad() { super.onViewLoad(); doLoadSequence(false, null); } @Override public void onViewUpdate() { super.onViewUpdate(); doLoadSequence(true, null); } protected void doLoadSequence(boolean reload, final OnActionBarReloadListener listener) { // Pre-load dialogs shareUtils.preloadShareDialog(getActivity()); shareUtils.preloadLinkDialog(getActivity()); final Entity userProvidedEntity = actionBarView.getEntity(); if(ticker != null) ticker.resetTicker(); if(userProvidedEntity != null) { if(reload) { if(viewsItem != null) viewsItem.setText(loadingText); if(commentsItem != null) commentsItem.setText(loadingText); if(likesItem != null) likesItem.setText(loadingText); if(sharesItem != null) sharesItem.setText(loadingText); if(likeButton != null) likeButton.setText(loadingText); if(onActionBarEventListener != null) { onActionBarEventListener.onUpdate(actionBarView); } } else { if(ticker != null) ticker.startTicker(); if(onActionBarEventListener != null) { onActionBarEventListener.onLoad(actionBarView); } } updateEntity(userProvidedEntity, reload, listener); } else { if(logger != null) { logger.warn("No entity provided to ActionBar. Load sequence aborted."); } } } @Override public void onViewError(Exception e) { super.onViewError(e); if(onActionBarEventListener != null) { onActionBarEventListener.onLoadFail(e); } } protected void updateEntity(final Entity entity, boolean reload, final OnActionBarReloadListener listener) { CacheableEntity localEntity = getLocalEntity(); if(localEntity == null) { ViewUtils.view(getActivity(), entity, new ViewAddListener() { @Override public void onError(SocializeException error) { SocializeLogger.e(error.getMessage(), error); getLike(entity.getKey(), listener); } @Override public void onCreate(View view) { // Entity will be set in like getLike(view.getEntity().getKey(), listener); } }); } else { if(reload) { if(localEntity.isLiked()) { getLike(entity.getKey(), listener); } else { getEntity(entity.getKey(), listener); } } else { // Just set everything from the cached version if(onActionBarEventListener != null) { onActionBarEventListener.onGetEntity(actionBarView, localEntity.getEntity()); } setEntityData(localEntity, listener); } } } public void reload() { reload(null); } public void reload(OnActionBarReloadListener listener) { if(actionBarView.getEntity() != null) { entityCache.remove(actionBarView.getEntity().getKey()); } doLoadSequence(true, listener); } protected void doLike(final ActionBarButton button, final OnActionBarReloadListener listener) { final CacheableEntity localEntity = getLocalEntity(); if(localEntity != null && localEntity.isLiked()) { // Unlike doUnLike(button, localEntity, listener); return; } button.showLoading(); LikeUtils.like(getActivity(), actionBarView.getEntity(), new LikeAddListener() { @Override public void onCancel() { button.hideLoading(); } @Override public void onError(SocializeException error) { logError("Error posting like", error); button.hideLoading(); } @Override public void onCreate(Like like) { CacheableEntity localEntity = setLocalEntity(like.getEntity()); localEntity.setLiked(true); localEntity.setLikeId(like.getId()); setEntityData(localEntity, listener); button.hideLoading(); if(onActionBarEventListener != null) { onActionBarEventListener.onPostLike(actionBarView, like); } } }); } protected void doUnLike(final ActionBarButton button, final CacheableEntity localEntity, final OnActionBarReloadListener listener) { button.showLoading(); LikeUtils.unlike(getActivity(), localEntity.getKey(), new LikeDeleteListener() { @Override public void onError(SocializeException error) { logError("Error deleting like", error); localEntity.setLiked(false); setEntityData(localEntity, listener); button.hideLoading(); } @Override public void onDelete() { localEntity.setLiked(false); setEntityData(localEntity, listener); button.hideLoading(); if(onActionBarEventListener != null) { onActionBarEventListener.onPostUnlike(actionBarView); } } }); } protected CacheableEntity getLocalEntity() { if(entityCache != null && actionBarView != null && actionBarView.getEntity() != null) { return entityCache.get(actionBarView.getEntity().getKey()); } return null; } protected CacheableEntity setLocalEntity(Entity entity) { // Don't override the action bar entity if it has changed. if(actionBarView.getEntity() != null) { if(entity.getKey().equals(actionBarView.getEntity().getKey())) { return entityCache.putEntity(entity); } else { return entityCache.putEntity(actionBarView.getEntity()); } } return entityCache.putEntity(entity); } protected void getLike(final String entityKey, final OnActionBarReloadListener listener) { // Get the like LikeUtils.getLike(getActivity(), entityKey, new LikeGetListener() { @Override public void onGet(Like like) { if(like != null) { CacheableEntity putEntity = setLocalEntity(like.getEntity()); putEntity.setLiked(true); putEntity.setLikeId(like.getId()); setEntityData(putEntity, listener); if(onActionBarEventListener != null) { onActionBarEventListener.onGetLike(actionBarView, like); } if(onActionBarEventListener != null) { onActionBarEventListener.onGetEntity(actionBarView, like.getEntity()); } } else { getEntity(entityKey, listener); } } @Override public void onError(SocializeException error) { if(error instanceof SocializeApiError) { if(((SocializeApiError)error).getResultCode() == 404) { // no like getEntity(entityKey, listener); // Don't log error return; } } if(onActionBarEventListener != null) { onActionBarEventListener.onLoadFail(error); } logError("Error retrieving entity data", error); } }); } protected void getEntity(String entityKey, final OnActionBarReloadListener listener) { EntityUtils.getEntity(getActivity(), entityKey, new EntityGetListener() { @Override public void onGet(Entity entity) { CacheableEntity putEntity = setLocalEntity(entity); setEntityData(putEntity, listener); if(onActionBarEventListener != null) { onActionBarEventListener.onGetEntity(actionBarView, entity); } } @Override public void onError(SocializeException error) { if(logger != null && logger.isDebugEnabled()) { logger.debug("Error retrieving entity data. This may be ok if the entity is new", error); } if(onActionBarEventListener != null) { onActionBarEventListener.onLoadFail(error); } } }); } protected void setEntityData(CacheableEntity ce, OnActionBarReloadListener listener) { Entity entity = ce.getEntity(); actionBarView.setEntity(entity); EntityStats stats = entity.getEntityStats(); if(stats != null) { if(viewsItem != null) viewsItem.setText(getCountText(stats.getViews())); if(commentsItem != null) commentsItem.setText(getCountText(stats.getComments())); if(likesItem != null) likesItem.setText(getCountText(stats.getLikes())); if(sharesItem != null) sharesItem.setText(getCountText(stats.getShares())); } if(likeButton != null) { if(ce.isLiked()) { likeButton.setText(localizationService.getString(I18NConstants.ACTIONBAR_UNLIKE)); likeButton.setIcon(likeIconHi); } else { likeButton.setText(localizationService.getString(I18NConstants.ACTIONBAR_LIKE)); likeButton.setIcon(likeIcon); } } if(listener != null) { listener.onReload(entity); } } protected String getCountText(Integer value) { String viewText = "0"; if(value != null) { int iVal = value; if(iVal >= 1000) { float fVal = (float) iVal / 1000.0f; viewText = countFormat.format(fVal); } else { viewText = value.toString(); } } return viewText; } protected void logError(String msg, Exception error) { if(logger != null) { logger.error(msg, error); } else { SocializeLogger.e(msg, error); } } public ActionBarButton getShareButton() { return shareButton; } public ActionBarButton getCommentButton() { return commentButton; } public ActionBarButton getLikeButton() { return likeButton; } public void setDrawables(Drawables drawables) { this.drawables = drawables; } public void setLogger(SocializeLogger logger) { this.logger = logger; } public void setButtonFactory(IBeanFactory<ActionBarButton> buttonFactory) { this.buttonFactory = buttonFactory; } public void setEntityCache(EntityCache entityCache) { this.entityCache = entityCache; } public ProgressDialogFactory getProgressDialogFactory() { return progressDialogFactory; } public void setProgressDialogFactory(ProgressDialogFactory progressDialogFactory) { this.progressDialogFactory = progressDialogFactory; } public void setDisplayUtils(DisplayUtils deviceUtils) { this.displayUtils = deviceUtils; } public void setTickerFactory(IBeanFactory<ActionBarTicker> tickerFactory) { this.tickerFactory = tickerFactory; } public void setItemFactory(IBeanFactory<ActionBarItem> itemFactory) { this.itemFactory = itemFactory; } public void setShareUtils(ShareUtilsProxy shareUtils) { this.shareUtils = shareUtils; } public void setCommentUtils(CommentUtilsProxy commentUtils) { this.commentUtils = commentUtils; } public void stopTicker() { if(ticker != null) { ticker.stopTicker(); } } public void startTicker() { if(ticker != null) { ticker.startTicker(); } } public void setOnActionBarEventListener(OnActionBarEventListener onActionBarEventListener) { this.onActionBarEventListener = onActionBarEventListener; } public OnActionBarEventListener getOnActionBarEventListener() { return onActionBarEventListener; } public OnCommentViewActionListener getOnCommentViewActionListener() { return onCommentViewActionListener; } public void setOnCommentViewActionListener(OnCommentViewActionListener onCommentViewActionListener) { this.onCommentViewActionListener = onCommentViewActionListener; } public void setLocalizationService(LocalizationService localizationService) { this.localizationService = localizationService; } }