package org.wordpress.android.ui.main;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.wordpress.android.R;
import org.wordpress.android.WordPress;
import org.wordpress.android.fluxc.model.SiteModel;
import org.wordpress.android.fluxc.store.AccountStore;
import org.wordpress.android.fluxc.store.SiteStore.OnSiteChanged;
import org.wordpress.android.ui.ActivityLauncher;
import org.wordpress.android.ui.RequestCodes;
import org.wordpress.android.ui.comments.CommentsListFragment.CommentStatusCriteria;
import org.wordpress.android.ui.posts.EditPostActivity;
import org.wordpress.android.ui.prefs.AppPrefs;
import org.wordpress.android.ui.stats.service.StatsService;
import org.wordpress.android.ui.themes.ThemeBrowserActivity;
import org.wordpress.android.util.AniUtils;
import org.wordpress.android.util.CoreEvents;
import org.wordpress.android.util.DateTimeUtils;
import org.wordpress.android.util.DisplayUtils;
import org.wordpress.android.util.ServiceUtils;
import org.wordpress.android.util.SiteUtils;
import org.wordpress.android.widgets.WPNetworkImageView;
import org.wordpress.android.widgets.WPTextView;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.inject.Inject;
import de.greenrobot.event.EventBus;
public class MySiteFragment extends Fragment
implements WPMainActivity.OnScrollToTopListener {
private static final long ALERT_ANIM_OFFSET_MS = 1000L;
private static final long ALERT_ANIM_DURATION_MS = 1000L;
public static final int HIDE_WP_ADMIN_YEAR = 2015;
public static final int HIDE_WP_ADMIN_MONTH = 9;
public static final int HIDE_WP_ADMIN_DAY = 7;
public static final String HIDE_WP_ADMIN_GMT_TIME_ZONE = "GMT";
private WPNetworkImageView mBlavatarImageView;
private WPTextView mBlogTitleTextView;
private WPTextView mBlogSubtitleTextView;
private LinearLayout mLookAndFeelHeader;
private RelativeLayout mThemesContainer;
private RelativeLayout mPeopleView;
private RelativeLayout mPageView;
private RelativeLayout mPlanContainer;
private View mConfigurationHeader;
private View mSettingsView;
private RelativeLayout mAdminView;
private View mFabView;
private LinearLayout mNoSiteView;
private ScrollView mScrollView;
private ImageView mNoSiteDrakeImageView;
private WPTextView mCurrentPlanNameTextView;
private int mFabTargetYTranslation;
private int mBlavatarSz;
@Inject AccountStore mAccountStore;
public static MySiteFragment newInstance() {
return new MySiteFragment();
}
public @Nullable SiteModel getSelectedSite() {
if (getActivity() instanceof WPMainActivity) {
WPMainActivity mainActivity = (WPMainActivity) getActivity();
return mainActivity.getSelectedSite();
}
return null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((WordPress) getActivity().getApplication()).component().inject(this);
}
@Override
public void onResume() {
super.onResume();
// Site details may have changed (e.g. via Settings and returning to this Fragment) so update the UI
refreshSelectedSiteDetails();
if (ServiceUtils.isServiceRunning(getActivity(), StatsService.class)) {
getActivity().stopService(new Intent(getActivity(), StatsService.class));
}
// redisplay hidden fab after a short delay
long delayMs = getResources().getInteger(R.integer.fab_animation_delay);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (isAdded() && (mFabView.getVisibility() != View.VISIBLE || mFabView.getTranslationY() != 0)) {
AniUtils.showFab(mFabView, true);
}
}
}, delayMs);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.my_site_fragment, container, false);
int fabHeight = getResources().getDimensionPixelSize(android.support.design.R.dimen.design_fab_size_normal);
int fabMargin = getResources().getDimensionPixelSize(R.dimen.fab_margin);
mFabTargetYTranslation = (fabHeight + fabMargin) * 2;
mBlavatarSz = getResources().getDimensionPixelSize(R.dimen.blavatar_sz_small);
mBlavatarImageView = (WPNetworkImageView) rootView.findViewById(R.id.my_site_blavatar);
mBlogTitleTextView = (WPTextView) rootView.findViewById(R.id.my_site_title_label);
mBlogSubtitleTextView = (WPTextView) rootView.findViewById(R.id.my_site_subtitle_label);
mLookAndFeelHeader = (LinearLayout) rootView.findViewById(R.id.my_site_look_and_feel_header);
mThemesContainer = (RelativeLayout) rootView.findViewById(R.id.row_themes);
mPeopleView = (RelativeLayout) rootView.findViewById(R.id.row_people);
mPlanContainer = (RelativeLayout) rootView.findViewById(R.id.row_plan);
mConfigurationHeader = rootView.findViewById(R.id.row_configuration);
mSettingsView = rootView.findViewById(R.id.row_settings);
mAdminView = (RelativeLayout) rootView.findViewById(R.id.row_admin);
mScrollView = (ScrollView) rootView.findViewById(R.id.scroll_view);
mNoSiteView = (LinearLayout) rootView.findViewById(R.id.no_site_view);
mNoSiteDrakeImageView = (ImageView) rootView.findViewById(R.id.my_site_no_site_view_drake);
mFabView = rootView.findViewById(R.id.fab_button);
mCurrentPlanNameTextView = (WPTextView) rootView.findViewById(R.id.my_site_current_plan_text_view);
mPageView = (RelativeLayout) rootView.findViewById(R.id.row_pages);
// hide the FAB the first time the fragment is created in order to animate it in onResume()
if (savedInstanceState == null) {
mFabView.setVisibility(View.INVISIBLE);
}
rootView.findViewById(R.id.card_view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ActivityLauncher.viewCurrentSite(getActivity(), getSelectedSite(), true);
}
});
mFabView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.addNewPostOrPageForResult(getActivity(), getSelectedSite(), false);
}
});
rootView.findViewById(R.id.switch_site).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showSitePicker();
}
});
rootView.findViewById(R.id.row_view_site).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentSite(getActivity(), getSelectedSite(), false);
}
});
rootView.findViewById(R.id.row_stats).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewBlogStats(getActivity(), getSelectedSite());
}
});
mPlanContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewBlogPlans(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.row_blog_posts).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogPosts(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.row_media).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogMedia(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.row_pages).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogPages(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.row_comments).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogComments(getActivity(), getSelectedSite());
}
});
mThemesContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogThemes(getActivity(), getSelectedSite());
}
});
mPeopleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewCurrentBlogPeople(getActivity(), getSelectedSite());
}
});
mSettingsView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewBlogSettingsForResult(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.row_admin).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityLauncher.viewBlogAdmin(getActivity(), getSelectedSite());
}
});
rootView.findViewById(R.id.my_site_add_site_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SitePickerActivity.addSite(getActivity(), mAccountStore.hasAccessToken());
}
});
return rootView;
}
private void showSitePicker() {
if (isAdded()) {
ActivityLauncher.showSitePickerForResult(getActivity(), getSelectedSite());
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RequestCodes.SITE_PICKER:
if (resultCode == Activity.RESULT_OK) {
//reset comments status filter
AppPrefs.setCommentsStatusFilter(CommentStatusCriteria.ALL);
}
break;
case RequestCodes.EDIT_POST:
// if user returned from adding a post via the FAB and it was saved as a local
// draft, briefly animate the background of the "Blog posts" view to give the
// user a cue as to where to go to return to that post
if (resultCode == Activity.RESULT_OK && getView() != null && data != null
&& data.getBooleanExtra(EditPostActivity.EXTRA_SAVED_AS_LOCAL_DRAFT, false)) {
showAlert(getView().findViewById(R.id.postsGlowBackground));
}
break;
}
}
private void showAlert(View view) {
if (isAdded() && view != null) {
Animation highlightAnimation = new AlphaAnimation(0.0f, 1.0f);
highlightAnimation.setInterpolator(new Interpolator() {
private float bounce(float t) {
return t * t * 24.0f;
}
public float getInterpolation(float t) {
t *= 1.1226f;
if (t < 0.184f) return bounce(t);
else if (t < 0.545f) return bounce(t - 0.40719f);
else if (t < 0.7275f) return -bounce(t - 0.6126f) + 1.0f;
else return 0.0f;
}
});
highlightAnimation.setStartOffset(ALERT_ANIM_OFFSET_MS);
highlightAnimation.setRepeatCount(1);
highlightAnimation.setRepeatMode(Animation.RESTART);
highlightAnimation.setDuration(ALERT_ANIM_DURATION_MS);
view.startAnimation(highlightAnimation);
}
}
private void refreshSelectedSiteDetails() {
if (!isAdded()) {
return;
}
SiteModel site = getSelectedSite();
if (site == null) {
mScrollView.setVisibility(View.GONE);
mFabView.setVisibility(View.GONE);
mNoSiteView.setVisibility(View.VISIBLE);
// if the screen height is too short, we can just hide the drake illustration
Activity activity = getActivity();
boolean drakeVisibility = DisplayUtils.getDisplayPixelHeight(activity) >= 500;
if (drakeVisibility) {
mNoSiteDrakeImageView.setVisibility(View.VISIBLE);
} else {
mNoSiteDrakeImageView.setVisibility(View.GONE);
}
return;
}
mScrollView.setVisibility(View.VISIBLE);
mNoSiteView.setVisibility(View.GONE);
toggleAdminVisibility(site);
int themesVisibility = ThemeBrowserActivity.isAccessible(getSelectedSite()) ? View.VISIBLE : View.GONE;
mLookAndFeelHeader.setVisibility(themesVisibility);
mThemesContainer.setVisibility(themesVisibility);
// show settings for all self-hosted to expose Delete Site
boolean isAdminOrSelfHosted = site.getHasCapabilityManageOptions() || !SiteUtils.isAccessedViaWPComRest(site);
mSettingsView.setVisibility(isAdminOrSelfHosted ? View.VISIBLE : View.GONE);
mPeopleView.setVisibility(site.getHasCapabilityListUsers() ? View.VISIBLE : View.GONE);
// if either people or settings is visible, configuration header should be visible
int settingsVisibility = (isAdminOrSelfHosted || site.getHasCapabilityListUsers()) ? View.VISIBLE : View.GONE;
mConfigurationHeader.setVisibility(settingsVisibility);
mBlavatarImageView.setImageUrl(SiteUtils.getSiteIconUrl(site, mBlavatarSz), WPNetworkImageView
.ImageType.BLAVATAR);
String homeUrl = SiteUtils.getHomeURLOrHostName(site);
String blogTitle = SiteUtils.getSiteNameOrHomeURL(site);
mBlogTitleTextView.setText(blogTitle);
mBlogSubtitleTextView.setText(homeUrl);
// Hide the Plan item if the Plans feature is not available for this blog
String planShortName = site.getPlanShortName();
if (!TextUtils.isEmpty(planShortName) && site.getHasCapabilityManageOptions()) {
if (site.isWPCom() || site.isAutomatedTransfer()) {
mCurrentPlanNameTextView.setText(planShortName);
mPlanContainer.setVisibility(View.VISIBLE);
} else {
// TODO: Support Jetpack plans
mPlanContainer.setVisibility(View.GONE);
}
} else {
mPlanContainer.setVisibility(View.GONE);
}
// Do not show pages menu item to Collaborators.
int pageVisibility = site.isSelfHostedAdmin() || site.getHasCapabilityEditPages() ? View.VISIBLE : View.GONE;
mPageView.setVisibility(pageVisibility);
}
private void toggleAdminVisibility(@Nullable final SiteModel site) {
if (site == null) {
return;
}
if (shouldHideWPAdmin(site)) {
mAdminView.setVisibility(View.GONE);
} else {
mAdminView.setVisibility(View.VISIBLE);
}
}
private boolean shouldHideWPAdmin(@Nullable final SiteModel site) {
if (site == null) {
return false;
}
if (!site.isWPCom()) {
return false;
} else {
Date dateCreated = DateTimeUtils.dateFromIso8601(mAccountStore.getAccount().getDate());
GregorianCalendar calendar = new GregorianCalendar(HIDE_WP_ADMIN_YEAR, HIDE_WP_ADMIN_MONTH,
HIDE_WP_ADMIN_DAY);
calendar.setTimeZone(TimeZone.getTimeZone(HIDE_WP_ADMIN_GMT_TIME_ZONE));
return dateCreated != null && dateCreated.after(calendar.getTime());
}
}
@Override
public void onScrollToTop() {
if (isAdded()) {
mScrollView.smoothScrollTo(0, 0);
}
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
/*
* animate the fab as the users scrolls the "My Site" page in the main activity's ViewPager
*/
@SuppressWarnings("unused")
public void onEventMainThread(CoreEvents.MainViewPagerScrolled event) {
mFabView.setTranslationY(mFabTargetYTranslation * event.mXOffset);
}
@SuppressWarnings("unused")
@Subscribe(threadMode = ThreadMode.MAIN)
public void onSiteChanged(OnSiteChanged event) {
if (!isAdded()) {
return;
}
refreshSelectedSiteDetails();
}
}