/* * The MIT License (MIT) * * Copyright (c) 2012-2014 lacolaco.net * * 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 net.lacolaco.smileessence.view.dialog; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Html; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.view.View; import android.widget.*; import com.android.volley.toolbox.NetworkImageView; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshListView; import net.lacolaco.smileessence.R; import net.lacolaco.smileessence.activity.MainActivity; import net.lacolaco.smileessence.command.Command; import net.lacolaco.smileessence.command.CommandOpenURL; import net.lacolaco.smileessence.data.ImageCache; import net.lacolaco.smileessence.entity.Account; import net.lacolaco.smileessence.entity.Tweet; import net.lacolaco.smileessence.entity.User; import net.lacolaco.smileessence.logging.Logger; import net.lacolaco.smileessence.notification.NotificationType; import net.lacolaco.smileessence.notification.Notificator; import net.lacolaco.smileessence.twitter.task.FollowTask; import net.lacolaco.smileessence.twitter.task.ShowFriendshipTask; import net.lacolaco.smileessence.twitter.task.UnfollowTask; import net.lacolaco.smileessence.twitter.task.UserTimelineTask; import net.lacolaco.smileessence.twitter.util.TwitterUtils; import net.lacolaco.smileessence.util.Themes; import net.lacolaco.smileessence.util.UIHandler; import net.lacolaco.smileessence.view.DialogHelper; import net.lacolaco.smileessence.view.adapter.CustomListAdapter; import net.lacolaco.smileessence.view.adapter.StatusListAdapter; import net.lacolaco.smileessence.viewmodel.StatusViewModel; import twitter4j.Paging; public class UserDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener, PullToRefreshBase.OnRefreshListener2 { // ------------------------------ FIELDS ------------------------------ private static final String KEY_USER_ID = "userID"; private StatusListAdapter adapter; private TextView textViewScreenName; private TextView textViewName; private TextView textViewURL; private TextView textViewLocate; private TextView textViewFollowed; private TextView textViewProtected; private TextView textViewDescription; private TextView textViewTweetCount; private TextView textViewFriendCount; private TextView textViewFollowerCount; private TextView textViewFavoriteCount; private NetworkImageView imageViewIcon; private NetworkImageView imageViewHeader; private Button buttonFollow; private PullToRefreshListView listViewTimeline; private TabHost tabHost; // --------------------- GETTER / SETTER METHODS --------------------- public long getUserID() { return getArguments().getLong(KEY_USER_ID); } public void setUserID(long userID) { Bundle args = new Bundle(); args.putLong(KEY_USER_ID, userID); setArguments(args); } // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface OnClickListener --------------------- @Override public void onClick(final View v) { final MainActivity activity = (MainActivity) getActivity(); final Account account = activity.getCurrentAccount(); account.tryGetUser(getUserID(), new Account.UserCallback() { @Override public void success(final User user) { switch (v.getId()) { case R.id.imageview_user_detail_menu: { openUserMenu(activity, user); break; } case R.id.imageview_user_detail_icon: { openUrl(user.getProfileImageUrlOriginal()); break; } case R.id.textview_user_detail_screenname: { openUrl(user.getUserHomeURL()); break; } case R.id.textview_user_detail_tweet_count: { openUrl(user.getUserHomeURL()); break; } case R.id.textview_user_detail_friend_count: { openUrl(String.format("%s/following", user.getUserHomeURL())); break; } case R.id.textview_user_detail_follower_count: { openUrl(String.format("%s/followers", user.getUserHomeURL())); break; } case R.id.textview_user_detail_favorite_count: { openUrl(String.format("%s/favorites", user.getUserHomeURL())); break; } case R.id.button_user_detail_follow: { ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands), new Runnable() { @Override public void run() { toggleFollowing(user, account, activity); } }); break; } } } @Override public void error() { dismiss(); } }); } // --------------------- Interface OnRefreshListener2 --------------------- @Override public void onPullDownToRefresh(final PullToRefreshBase refreshView) { final MainActivity activity = (MainActivity) getActivity(); final Account currentAccount = activity.getCurrentAccount(); Paging paging = TwitterUtils.getPaging(activity.getRequestCountPerPage()); if (adapter.getCount() > 0) { paging.setSinceId(adapter.getTopID()); } new UserTimelineTask(currentAccount, getUserID(), paging).onDoneUI(tweets -> { for (int i = tweets.size() - 1; i >= 0; i--) { adapter.addToTop(new StatusViewModel(tweets.get(i))); } updateListView(refreshView.getRefreshableView(), adapter, true); refreshView.onRefreshComplete(); }).execute(); } @Override public void onPullUpToRefresh(final PullToRefreshBase refreshView) { final MainActivity activity = (MainActivity) getActivity(); final Account currentAccount = activity.getCurrentAccount(); Paging paging = TwitterUtils.getPaging(activity.getRequestCountPerPage()); if (adapter.getCount() > 0) { paging.setMaxId(adapter.getLastID() - 1); } new UserTimelineTask(currentAccount, getUserID(), paging).onDoneUI(tweets -> { for (Tweet tweet : tweets) { adapter.addToBottom(new StatusViewModel(tweet)); } updateListView(refreshView.getRefreshableView(), adapter, false); refreshView.onRefreshComplete(); }).execute(); } // ------------------------ OVERRIDE METHODS ------------------------ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { MainActivity activity = (MainActivity) getActivity(); View v = activity.getLayoutInflater().inflate(R.layout.dialog_user_detail, null); View menu = v.findViewById(R.id.imageview_user_detail_menu); menu.setOnClickListener(this); textViewScreenName = (TextView) v.findViewById(R.id.textview_user_detail_screenname); textViewScreenName.setOnClickListener(this); textViewName = (TextView) v.findViewById(R.id.textview_user_detail_name); textViewURL = (TextView) v.findViewById(R.id.textview_user_detail_url); textViewLocate = (TextView) v.findViewById(R.id.textview_user_detail_locate); textViewFollowed = (TextView) v.findViewById(R.id.textview_user_detail_followed); textViewProtected = (TextView) v.findViewById(R.id.texttview_user_detail_protected); textViewDescription = (TextView) v.findViewById(R.id.textview_user_detail_description); textViewTweetCount = (TextView) v.findViewById(R.id.textview_user_detail_tweet_count); textViewTweetCount.setOnClickListener(this); textViewFriendCount = (TextView) v.findViewById(R.id.textview_user_detail_friend_count); textViewFriendCount.setOnClickListener(this); textViewFollowerCount = (TextView) v.findViewById(R.id.textview_user_detail_follower_count); textViewFollowerCount.setOnClickListener(this); textViewFavoriteCount = (TextView) v.findViewById(R.id.textview_user_detail_favorite_count); textViewFavoriteCount.setOnClickListener(this); imageViewIcon = (NetworkImageView) v.findViewById(R.id.imageview_user_detail_icon); imageViewIcon.setOnClickListener(this); imageViewHeader = (NetworkImageView) v.findViewById(R.id.imageview_user_detail_header); buttonFollow = (Button) v.findViewById(R.id.button_user_detail_follow); buttonFollow.setOnClickListener(this); listViewTimeline = (PullToRefreshListView) v.findViewById(R.id.listview_user_detail_timeline); tabHost = (TabHost) v.findViewById(android.R.id.tabhost); tabHost.setup(); TabHost.TabSpec tab1 = tabHost.newTabSpec("tab1").setContent(R.id.tab1).setIndicator(getString(R.string.user_detail_tab_info)); tabHost.addTab(tab1); TabHost.TabSpec tab2 = tabHost.newTabSpec("tab2").setContent(R.id.tab2).setIndicator(getString(R.string.user_detail_tab_timeline)); tabHost.addTab(tab2); tabHost.setCurrentTab(0); final Account account = activity.getCurrentAccount(); account.tryGetUser(getUserID(), new Account.UserCallback() { @Override public void success(User user) { try { initUserData(user, account); } catch (Exception e) { Logger.error(e); error(); } } @Override public void error() { dismiss(); } }); return new AlertDialog.Builder(activity) .setView(v) .setCancelable(true) .create(); } private void executeUserTimelineTask(final User user, final Account account, final StatusListAdapter adapter) { tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.GONE); new UserTimelineTask(account, user.getId()).onDoneUI(tweets -> { for (Tweet tweet : tweets) { adapter.addToBottom(new StatusViewModel(tweet)); } adapter.updateForce(); tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.VISIBLE); }).execute(); } private String getHtmlDescription(String description) { if (TextUtils.isEmpty(description)) { return ""; } String html = description; html = html.replaceAll("https?://[\\w/:%#\\$&\\?\\(\\)~\\.=\\+\\-]+", "$0"); html = html.replaceAll("@([a-zA-Z0-9_]+)", "$0"); html = html.replaceAll("\r\n", "
"); return html; } private void initUserData(User user, final Account account) { textViewName.setText(user.getName()); textViewScreenName.setText(user.getScreenName()); if (TextUtils.isEmpty(user.getLocation())) { textViewLocate.setVisibility(View.GONE); } else { textViewLocate.setText(user.getLocation()); } if (TextUtils.isEmpty(user.getUrl())) { textViewURL.setVisibility(View.GONE); } else { textViewURL.setText(user.getUrl()); } textViewTweetCount.setText(String.valueOf(user.getStatusesCount())); textViewFriendCount.setText(String.valueOf(user.getFriendsCount())); textViewFollowerCount.setText(String.valueOf(user.getFollowersCount())); textViewFavoriteCount.setText(String.valueOf(user.getFavoritesCount())); textViewProtected.setVisibility(user.isProtected() ? View.VISIBLE : View.GONE); String htmlDescription = getHtmlDescription(user.getDescription()); textViewDescription.setText(Html.fromHtml(htmlDescription)); textViewDescription.setMovementMethod(LinkMovementMethod.getInstance()); ImageCache.getInstance().setImageToView(user.getProfileImageUrlOriginal(), imageViewIcon); ImageCache.getInstance().setImageToView(user.getProfileBannerUrl(), imageViewHeader); MainActivity activity = (MainActivity) getActivity(); adapter = new StatusListAdapter(activity); listViewTimeline.setAdapter(adapter); listViewTimeline.setOnRefreshListener(this); executeUserTimelineTask(user, account, adapter); updateRelationship(activity, user.getId()); } private void lockFollowButton(Activity activity) { buttonFollow.setText(R.string.user_detail_loading); buttonFollow.setBackground(activity.getResources().getDrawable(R.drawable.button_round_gray)); buttonFollow.setEnabled(false); } private void openUrl(String url) { new CommandOpenURL(getActivity(), url).execute(); } private void openUserMenu(final MainActivity activity, final User user) { UserMenuDialogFragment menuFragment = new UserMenuDialogFragment() { @Override protected void executeCommand(Command command) { super.executeCommand(command); new UIHandler().postDelayed(() -> { if (UserDetailDialogFragment.this.isDetached()) { return; } updateRelationship(activity, user.getId()); }, 1000); } }; menuFragment.setUserID(user.getId()); DialogHelper.showDialog(activity, menuFragment); } private void setFollowButtonState(boolean isFollowing, Drawable unfollowColor, Drawable followColor) { buttonFollow.setText(isFollowing ? R.string.user_detail_unfollow : R.string.user_detail_follow); buttonFollow.setBackground(isFollowing ? unfollowColor : followColor); buttonFollow.setTag(isFollowing); buttonFollow.setEnabled(true); } private void toggleFollowing(final User user, final Account account, final Activity activity) { lockFollowButton(activity); Boolean isFollowing = buttonFollow.getTag() != null ? (Boolean) buttonFollow.getTag() : false; if (isFollowing) { new UnfollowTask(account, user.getId()).onDoneUI(result -> { if (result != null) { Notificator.getInstance().publish(R.string.notice_unfollow_succeeded); } else { Notificator.getInstance().publish(R.string.notice_unfollow_failed, NotificationType.ALERT); } updateRelationship(activity, user.getId()); buttonFollow.setEnabled(true); }).execute(); } else { new FollowTask(account, user.getId()).onDoneUI(result -> { if (result != null) { Notificator.getInstance().publish(R.string.notice_follow_succeeded); } else { Notificator.getInstance().publish(R.string.notice_follow_failed, NotificationType.ALERT); } updateRelationship(activity, user.getId()); buttonFollow.setEnabled(true); }).execute(); } } protected void updateListView(AbsListView absListView, CustomListAdapter adapter, boolean addedToTop) { int before = adapter.getCount(); adapter.notifyDataSetChanged(); // synchronized call (not adapter#updateForce()) int after = adapter.getCount(); int increments = after - before; if (increments > 0) { adapter.setNotifiable(false); if (addedToTop) { absListView.setSelection(increments + 1); absListView.smoothScrollToPositionFromTop(increments, 0); absListView.setSelection(increments); } else { absListView.smoothScrollToPositionFromTop(before, 0); } if (increments == 1) { adapter.setNotifiable(true); } } else { adapter.setNotifiable(true); } } private void updateRelationship(Activity activity, final long userId) { MainActivity mainActivity = (MainActivity) activity; Account account = mainActivity.getCurrentAccount(); if (userId == account.userID) { textViewFollowed.setText(R.string.user_detail_followed_is_me); buttonFollow.setVisibility(View.GONE); } else { int theme = mainActivity.getThemeIndex(); lockFollowButton(activity); textViewFollowed.setText(R.string.user_detail_loading); final Drawable red = Themes.getStyledDrawable(activity, theme, R.attr.button_round_red); final Drawable blue = Themes.getStyledDrawable(activity, theme, R.attr.button_round_blue); new ShowFriendshipTask(account, userId).onDoneUI(relationship -> { if (relationship != null) { boolean isFollowing = relationship.isSourceFollowingTarget(); boolean isFollowed = relationship.isSourceFollowedByTarget(); setFollowButtonState(isFollowing, red, blue); textViewFollowed.setText(isFollowed ? R.string.user_detail_followed : R.string.user_detail_not_followed); } }).execute(); } } }