diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverActivity.java index b511422e43a3..21770b29b32e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverActivity.java @@ -87,7 +87,7 @@ private void refreshContent() { share(ShareAction.SHARE_TO_POST, visibleSites.get(0).getId()); } else { // display a fragment with list of sites and list of actions the user can perform - initShareFragment(false); + initShareFragment(); } } else { // start the login flow and wait onActivityResult @@ -107,9 +107,9 @@ private void downloadExternalMedia() { } } - private void initShareFragment(boolean afterLogin) { + private void initShareFragment() { ShareIntentReceiverFragment shareIntentReceiverFragment = ShareIntentReceiverFragment - .newInstance(!isSharingText(), loadLastUsedBlogLocalId(), afterLogin); + .newInstance(!isSharingText(), loadLastUsedBlogLocalId()); getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, shareIntentReceiverFragment, ShareIntentReceiverFragment.TAG) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverFragment.java index 875ea6cd9299..2f118bbde556 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ShareIntentReceiverFragment.java @@ -7,21 +7,20 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.Adapter; -import androidx.recyclerview.widget.RecyclerView.ViewHolder; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.fluxc.store.AccountStore; -import org.wordpress.android.ui.accounts.login.LoginHeaderViewHolder; import org.wordpress.android.ui.main.SitePickerAdapter; -import org.wordpress.android.ui.main.SitePickerAdapter.HeaderHandler; import org.wordpress.android.ui.main.SitePickerAdapter.SiteList; +import org.wordpress.android.ui.main.SitePickerAdapter.ViewHolderHandler; import org.wordpress.android.ui.media.MediaBrowserActivity; import org.wordpress.android.ui.posts.EditPostActivity; import org.wordpress.android.util.image.ImageManager; @@ -33,7 +32,6 @@ public class ShareIntentReceiverFragment extends Fragment { private static final String ARG_SHARING_MEDIA = "ARG_SHARING_MEDIA"; private static final String ARG_LAST_USED_BLOG_LOCAL_ID = "ARG_LAST_USED_BLOG_LOCAL_ID"; - private static final String ARG_AFTER_LOGIN = "ARG_AFTER_LOGIN"; @Inject AccountStore mAccountStore; @Inject ImageManager mImageManager; @@ -45,17 +43,14 @@ public class ShareIntentReceiverFragment extends Fragment { private boolean mSharingMediaFile; private int mLastUsedBlogLocalId; - private boolean mAfterLogin; private RecyclerView mRecyclerView; private View mBottomButtonsContainer; private View mBottomButtonsShadow; - public static ShareIntentReceiverFragment newInstance(boolean sharingMediaFile, int lastUsedBlogLocalId, - boolean afterLogin) { + public static ShareIntentReceiverFragment newInstance(boolean sharingMediaFile, int lastUsedBlogLocalId) { ShareIntentReceiverFragment fragment = new ShareIntentReceiverFragment(); Bundle args = new Bundle(); args.putBoolean(ARG_SHARING_MEDIA, sharingMediaFile); - args.putBoolean(ARG_AFTER_LOGIN, afterLogin); args.putInt(ARG_LAST_USED_BLOG_LOCAL_ID, lastUsedBlogLocalId); fragment.setArguments(args); return fragment; @@ -81,7 +76,7 @@ public void onAttach(Context context) { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.login_epilogue_screen, container, false); + ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.share_intent_receiver_fragment, container, false); initButtonsContainer(layout); initShareActionPostButton(layout); initShareActionMediaButton(layout, mSharingMediaFile); @@ -94,7 +89,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((WordPress) getActivity().getApplication()).component().inject(this); mSharingMediaFile = getArguments().getBoolean(ARG_SHARING_MEDIA); - mAfterLogin = getArguments().getBoolean(ARG_AFTER_LOGIN); mLastUsedBlogLocalId = getArguments().getInt(ARG_LAST_USED_BLOG_LOCAL_ID); loadSavedState(savedInstanceState); } @@ -122,15 +116,12 @@ private void initButtonsContainer(ViewGroup layout) { private void initShareActionPostButton(final ViewGroup layout) { mSharePostBtn = layout.findViewById(R.id.primary_button); addShareActionListener(mSharePostBtn, ShareAction.SHARE_TO_POST); - mSharePostBtn.setVisibility(View.VISIBLE); - mSharePostBtn.setText(R.string.share_action_post); } private void initShareActionMediaButton(final ViewGroup layout, boolean sharingMediaFile) { mShareMediaBtn = layout.findViewById(R.id.secondary_button); addShareActionListener(mShareMediaBtn, ShareAction.SHARE_TO_MEDIA_LIBRARY); mShareMediaBtn.setVisibility(sharingMediaFile ? View.VISIBLE : View.GONE); - mShareMediaBtn.setText(R.string.share_action_media); } private void addShareActionListener(final Button button, final ShareAction shareAction) { @@ -184,28 +175,37 @@ public void run() { return mAdapter; } - private HeaderHandler createHeaderHandler() { - return new HeaderHandler() { + private ViewHolderHandler createHeaderHandler() { + return new ViewHolderHandler() { @Override - public ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, - boolean attachToRoot) { - return new LoginHeaderViewHolder(layoutInflater.inflate(R.layout.login_epilogue_header, parent, false)); + public HeaderViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, + boolean attachToRoot) { + return new HeaderViewHolder( + layoutInflater.inflate(R.layout.share_intent_receiver_header, parent, false)); } @Override - public void onBindViewHolder(ViewHolder holder, SiteList sites) { - refreshAccountDetails((LoginHeaderViewHolder) holder, sites); + public void onBindViewHolder(HeaderViewHolder holder, SiteList sites) { + if (!isAdded()) { + return; + } + holder.bindText(getString( + sites.size() == 1 ? R.string.share_intent_adding_to : R.string.share_intent_pick_site)); } }; } - private void refreshAccountDetails(LoginHeaderViewHolder holder, SiteList sites) { - if (!isAdded()) { - return; + static class HeaderViewHolder extends RecyclerView.ViewHolder { + private final TextView mHeaderTextView; + + HeaderViewHolder(View view) { + super(view); + mHeaderTextView = view.findViewById(R.id.login_epilogue_header_sites_subheader); + } + + void bindText(String text) { + mHeaderTextView.setText(text); } - holder.updateLoggedInAsHeading(getContext(), mImageManager, mAfterLogin, mAccountStore.getAccount()); - holder.showSitesHeading( - getString(sites.size() == 1 ? R.string.share_intent_adding_to : R.string.share_intent_pick_site)); } enum ShareAction { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginEpilogueFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginEpilogueFragment.java index 3f952b29494d..9b6caa6a0dd9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginEpilogueFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginEpilogueFragment.java @@ -18,11 +18,12 @@ import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; +import org.wordpress.android.fluxc.model.AccountModel; import org.wordpress.android.fluxc.model.SiteModel; import org.wordpress.android.login.LoginBaseFormFragment; import org.wordpress.android.ui.main.SitePickerAdapter; import org.wordpress.android.ui.main.SitePickerAdapter.SiteList; -import org.wordpress.android.util.GravatarUtils; +import org.wordpress.android.ui.main.SitePickerAdapter.ViewHolderHandler; import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.analytics.AnalyticsUtils; import org.wordpress.android.util.image.ImageManager; @@ -40,8 +41,6 @@ public class LoginEpilogueFragment extends LoginBaseFormFragment { + if (mLoginEpilogueListener != null) { + mLoginEpilogueListener.onContinue(); } }); } @@ -160,33 +142,45 @@ public void onBeforeLoad(boolean isEmpty) { @Override public void onAfterLoad() { - mSitesList.post(new Runnable() { - @Override - public void run() { - if (!isAdded()) { - return; - } - - if (mSitesList.computeVerticalScrollRange() > mSitesList.getHeight()) { - mBottomShadow.setVisibility(View.VISIBLE); - } else { - mBottomShadow.setVisibility(View.GONE); - } + mSitesList.post(() -> { + if (!isAdded()) { + return; + } + + if (mSitesList.computeVerticalScrollRange() > mSitesList.getHeight()) { + mBottomShadow.setVisibility(View.VISIBLE); + } else { + mBottomShadow.setVisibility(View.GONE); } }); } - }, new SitePickerAdapter.HeaderHandler() { - @Override - public RecyclerView.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, - boolean attachToRoot) { - return new LoginHeaderViewHolder(layoutInflater.inflate(R.layout.login_epilogue_header, parent, false)); - } + }, + new SitePickerAdapter.ViewHolderHandler() { + @Override + public LoginHeaderViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, + boolean attachToRoot) { + return new LoginHeaderViewHolder( + layoutInflater.inflate(R.layout.login_epilogue_header, parent, false)); + } - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, SiteList sites) { - refreshAccountDetails((LoginHeaderViewHolder) holder, sites); - } - }, mOldSitesIds); + @Override + public void onBindViewHolder(LoginHeaderViewHolder holder, SiteList sites) { + bindHeaderViewHolder(holder, sites); + } + }, + new ViewHolderHandler() { + @Override + public LoginFooterViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, + boolean attachToRoot) { + return new LoginFooterViewHolder( + layoutInflater.inflate(R.layout.login_epilogue_footer, parent, false)); + } + + @Override + public void onBindViewHolder(LoginFooterViewHolder holder, SiteList sites) { + bindFooterViewHolder(holder, sites); + } + }, mOldSitesIds); } @Override @@ -209,35 +203,42 @@ public void onResume() { } } - private void refreshAccountDetails(LoginHeaderViewHolder holder, SiteList sites) { + private void bindHeaderViewHolder(LoginHeaderViewHolder holder, SiteList sites) { if (!isAdded()) { return; } final boolean isWpcom = mAccountStore.hasAccessToken(); + final boolean hasSites = sites.size() != 0; if (isWpcom) { - holder.updateLoggedInAsHeading(getContext(), mImageManager, true, mAccountStore.getAccount()); - } else if (sites.size() != 0) { - SiteModel site = mSiteStore.getSiteByLocalId(sites.get(0).getLocalId()); - int avatarSz = getResources().getDimensionPixelSize(R.dimen.avatar_sz_large); - - String avatarUrl = GravatarUtils.gravatarFromEmail(site.getEmail(), avatarSz); - String username = site.getUsername(); - String displayName = site.getDisplayName(); - - holder.updateLoggedInAsHeading(getContext(), mImageManager, true, avatarUrl, username, displayName); + final AccountModel account = mAccountStore.getAccount(); + holder.updateLoggedInAsHeading(getContext(), mImageManager, account); + } else if (hasSites) { + final SiteModel site = mSiteStore.getSiteByLocalId(sites.get(0).getLocalId()); + holder.updateLoggedInAsHeading(getContext(), mImageManager, site); } - if (sites.size() == 0) { - holder.hideSitesHeading(); - mConnectMore.setText(R.string.connect_site); - } else { + if (hasSites) { holder.showSitesHeading(StringUtils.getQuantityString( - getActivity(), R.string.days_quantity_one, R.string.login_epilogue_mysites_one, + getActivity(), R.string.login_epilogue_mysites_one, R.string.login_epilogue_mysites_one, R.string.login_epilogue_mysites_other, sites.size())); + } else { + holder.hideSitesHeading(); + } + } - mConnectMore.setText(R.string.connect_more); + private void bindFooterViewHolder(LoginFooterViewHolder holder, SiteList sites) { + holder.itemView.setVisibility(mShowAndReturn ? View.GONE : View.VISIBLE); + holder.itemView.setOnClickListener(v -> { + if (mLoginEpilogueListener != null) { + mLoginEpilogueListener.onConnectAnotherSite(); + } + }); + if (sites.size() == 0) { + holder.bindText(getString(R.string.connect_site)); + } else { + holder.bindText(getString(R.string.connect_more)); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginFooterViewHolder.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginFooterViewHolder.java new file mode 100644 index 000000000000..0526743807c9 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginFooterViewHolder.java @@ -0,0 +1,21 @@ +package org.wordpress.android.ui.accounts.login; + +import android.view.View; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import org.wordpress.android.R; + +public class LoginFooterViewHolder extends RecyclerView.ViewHolder { + private final TextView mFooterTextView; + + LoginFooterViewHolder(View view) { + super(view); + mFooterTextView = view.findViewById(R.id.footer_text_view); + } + + public void bindText(String text) { + mFooterTextView.setText(text); + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginHeaderViewHolder.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginHeaderViewHolder.java index a276d86cd643..567b2760336a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginHeaderViewHolder.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginHeaderViewHolder.java @@ -10,70 +10,74 @@ import org.wordpress.android.R; import org.wordpress.android.fluxc.model.AccountModel; +import org.wordpress.android.fluxc.model.SiteModel; import org.wordpress.android.util.GravatarUtils; import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.image.ImageManager; -import org.wordpress.android.util.image.ImageType; + +import static org.wordpress.android.util.image.ImageType.AVATAR_WITHOUT_BACKGROUND; /** * ViewHolder for a RecyclerView header used on screens shown after a user logs in. */ -public class LoginHeaderViewHolder extends RecyclerView.ViewHolder { - private final View mLoggedInAsHeading; - private final View mUserDetailsCard; +class LoginHeaderViewHolder extends RecyclerView.ViewHolder { private final ImageView mAvatarImageView; private final TextView mDisplayNameTextView; private final TextView mUsernameTextView; private final TextView mMySitesHeadingTextView; - public LoginHeaderViewHolder(View view) { + LoginHeaderViewHolder(View view) { super(view); - mLoggedInAsHeading = view.findViewById(R.id.logged_in_as_heading); - mUserDetailsCard = view.findViewById(R.id.user_details_card); - mAvatarImageView = view.findViewById(R.id.avatar); - mDisplayNameTextView = view.findViewById(R.id.display_name); - mUsernameTextView = view.findViewById(R.id.username); - mMySitesHeadingTextView = view.findViewById(R.id.my_sites_heading); + mAvatarImageView = view.findViewById(R.id.login_epilogue_header_avatar); + mDisplayNameTextView = view.findViewById(R.id.login_epilogue_header_title); + mUsernameTextView = view.findViewById(R.id.login_epilogue_header_subtitle); + mMySitesHeadingTextView = view.findViewById(R.id.login_epilogue_header_sites_subheader); + } + + void updateLoggedInAsHeading(Context context, ImageManager imageManager, AccountModel account) { + final String avatarUrl = constructGravatarUrl(context, account); + final String username = account.getUserName(); + final String displayName = account.getDisplayName(); + updateLoggedInAsHeading(imageManager, avatarUrl, username, displayName); } - public void updateLoggedInAsHeading(Context context, ImageManager imageManager, boolean isAfterLogin, - AccountModel defaultAccount) { - updateLoggedInAsHeading(context, imageManager, isAfterLogin, constructGravatarUrl(context, defaultAccount), - defaultAccount.getUserName(), defaultAccount.getDisplayName()); + void updateLoggedInAsHeading(Context context, ImageManager imageManager, SiteModel site) { + final String avatarUrl = constructGravatarUrl(context, site); + final String username = site.getUsername(); + final String displayName = site.getDisplayName(); + updateLoggedInAsHeading(imageManager, avatarUrl, username, displayName); } - public void updateLoggedInAsHeading(Context context, ImageManager imageManager, boolean isAfterLogin, - String avatarUrl, String username, String displayName) { - if (isAfterLogin) { - mLoggedInAsHeading.setVisibility(View.VISIBLE); - mUserDetailsCard.setVisibility(View.VISIBLE); - imageManager.loadIntoCircle(mAvatarImageView, ImageType.AVATAR_WITHOUT_BACKGROUND, - StringUtils.notNullStr(avatarUrl)); - mUsernameTextView.setText(context.getString(R.string.login_username_at, username)); - - if (!TextUtils.isEmpty(displayName)) { - mDisplayNameTextView.setText(displayName); - } else { - mDisplayNameTextView.setText(username); - } + void updateLoggedInAsHeading(ImageManager imageManager, String avatarUrl, String username, String displayName) { + imageManager.loadIntoCircle(mAvatarImageView, AVATAR_WITHOUT_BACKGROUND, StringUtils.notNullStr(avatarUrl)); + + mUsernameTextView.setText(username); + + if (!TextUtils.isEmpty(displayName)) { + mDisplayNameTextView.setText(displayName); } else { - imageManager.cancelRequestAndClearImageView(mAvatarImageView); - mLoggedInAsHeading.setVisibility(View.GONE); - mUserDetailsCard.setVisibility(View.GONE); + mDisplayNameTextView.setText(username); } } - public void showSitesHeading(String text) { + void showSitesHeading(String text) { mMySitesHeadingTextView.setVisibility(View.VISIBLE); mMySitesHeadingTextView.setText(text); } - public void hideSitesHeading() { + void hideSitesHeading() { mMySitesHeadingTextView.setVisibility(View.GONE); } + private int getAvatarSize(Context context) { + return context.getResources().getDimensionPixelSize(R.dimen.avatar_sz_large); + } + private String constructGravatarUrl(Context context, AccountModel account) { - int avatarSz = context.getResources().getDimensionPixelSize(R.dimen.avatar_sz_large); - return GravatarUtils.fixGravatarUrl(account.getAvatarUrl(), avatarSz); + return GravatarUtils.fixGravatarUrl(account.getAvatarUrl(), getAvatarSize(context)); + } + + private String constructGravatarUrl(Context context, SiteModel site) { + return GravatarUtils.gravatarFromEmail(site.getEmail(), getAvatarSize(context)); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SignupEpilogueFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SignupEpilogueFragment.java index 8636f0df4858..86f1fe5dd758 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SignupEpilogueFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SignupEpilogueFragment.java @@ -16,11 +16,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.Button; import android.widget.EditText; -import android.widget.ImageButton; +import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.LayoutRes; @@ -28,6 +28,8 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; +import androidx.core.widget.NestedScrollView; +import androidx.core.widget.NestedScrollView.OnScrollChangeListener; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.yalantis.ucrop.UCrop; @@ -91,7 +93,7 @@ public class SignupEpilogueFragment extends LoginBaseFormFragment showBottomShadowIfNeeded()); + // We must use onGlobalLayout here otherwise canScrollVertically will always return false + mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { + @Override public void onGlobalLayout() { + mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + showBottomShadowIfNeeded(); + } + }); + } + + private void showBottomShadowIfNeeded() { + if (mScrollView != null) { + final boolean canScrollDown = mScrollView.canScrollVertically(1); + if (mBottomShadow != null) { + mBottomShadow.setVisibility(canScrollDown ? View.VISIBLE : View.GONE); + } + } } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java index db937b631ce7..22df125dbf83 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/SitePickerAdapter.java @@ -1,7 +1,6 @@ package org.wordpress.android.ui.main; import android.content.Context; -import android.graphics.Typeface; import android.os.AsyncTask; import android.text.TextUtils; import android.util.TypedValue; @@ -57,10 +56,10 @@ public interface OnDataLoadedListener { void onAfterLoad(); } - public interface HeaderHandler { - RecyclerView.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, - boolean attachToRoot); - void onBindViewHolder(RecyclerView.ViewHolder holder, SiteList sites); + public interface ViewHolderHandler { + T onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent, boolean attachToRoot); + + void onBindViewHolder(T holder, SiteList sites); } private final @LayoutRes int mItemLayoutReourceId; @@ -76,7 +75,8 @@ RecyclerView.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGr private final LayoutInflater mInflater; private final HashSet mSelectedPositions = new HashSet<>(); - private final HeaderHandler mHeaderHandler; + private final ViewHolderHandler mHeaderHandler; + private final ViewHolderHandler mFooterHandler; private boolean mIsMultiSelectEnabled; private final boolean mIsInSearchMode; @@ -98,6 +98,7 @@ RecyclerView.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGr private static final int VIEW_TYPE_HEADER = 0; private static final int VIEW_TYPE_ITEM = 1; + private static final int VIEW_TYPE_FOOTER = 2; @Inject AccountStore mAccountStore; @Inject SiteStore mSiteStore; @@ -140,7 +141,20 @@ public SitePickerAdapter(Context context, String lastSearch, boolean isInSearchMode, OnDataLoadedListener dataLoadedListener, - HeaderHandler headerHandler, + ViewHolderHandler headerHandler, + ArrayList ignoreSitesIds) { + this(context, itemLayoutResourceId, currentLocalBlogId, lastSearch, isInSearchMode, dataLoadedListener, + headerHandler, null, ignoreSitesIds); + } + + public SitePickerAdapter(Context context, + @LayoutRes int itemLayoutResourceId, + int currentLocalBlogId, + String lastSearch, + boolean isInSearchMode, + OnDataLoadedListener dataLoadedListener, + ViewHolderHandler headerHandler, + ViewHolderHandler footerHandler, ArrayList ignoreSitesIds) { super(); ((WordPress) context.getApplicationContext()).component().inject(this); @@ -165,6 +179,7 @@ public SitePickerAdapter(Context context, context.getResources().getInteger(R.integer.selected_list_item_opacity)); mHeaderHandler = headerHandler; + mFooterHandler = footerHandler; mSelectedItemPos = getPositionOffset(); mIgnoreSitesIds = ignoreSitesIds; @@ -174,7 +189,7 @@ public SitePickerAdapter(Context context, @Override public int getItemCount() { - return (mHeaderHandler != null ? 1 : 0) + mSites.size(); + return (mHeaderHandler != null ? 1 : 0) + mSites.size() + (mFooterHandler != null ? 1 : 0); } private int getSitesCount() { @@ -183,8 +198,11 @@ private int getSitesCount() { @Override public long getItemId(int position) { - if (mHeaderHandler != null && position == 0) { - return RecyclerView.NO_ID; + int viewType = getItemViewType(position); + if (viewType == VIEW_TYPE_HEADER) { + return -1; + } else if (viewType == VIEW_TYPE_FOOTER) { + return -2; } else { return getItem(position).mLocalId; } @@ -192,10 +210,12 @@ public long getItemId(int position) { @Override public int getItemViewType(int position) { - if (mHeaderHandler == null) { - return VIEW_TYPE_ITEM; + if (mHeaderHandler != null && position == 0) { + return VIEW_TYPE_HEADER; + } else if (mFooterHandler != null && position == getItemCount() - 1) { + return VIEW_TYPE_FOOTER; } else { - return position == 0 ? VIEW_TYPE_HEADER : VIEW_TYPE_ITEM; + return VIEW_TYPE_ITEM; } } @@ -221,6 +241,8 @@ void setOnSiteClickListener(OnSiteClickListener listener) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_HEADER) { return mHeaderHandler.onCreateViewHolder(mInflater, parent, false); + } else if (viewType == VIEW_TYPE_FOOTER) { + return mFooterHandler.onCreateViewHolder(mInflater, parent, false); } else { View itemView = mInflater.inflate(mItemLayoutReourceId, parent, false); return new SiteViewHolder(itemView); @@ -236,12 +258,17 @@ public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, return; } + if (viewType == VIEW_TYPE_FOOTER) { + mFooterHandler.onBindViewHolder(viewHolder, mSites); + return; + } + SiteRecord site = getItem(position); final SiteViewHolder holder = (SiteViewHolder) viewHolder; holder.mTxtTitle.setText(site.getBlogNameOrHomeURL()); holder.mTxtDomain.setText(site.mHomeURL); - mImageManager.load(holder.mImgBlavatar, ImageType.BLAVATAR, site.mBlavatarUrl); + mImageManager.loadWithRoundedCorners(holder.mImgBlavatar, ImageType.BLAVATAR_ROUNDED, site.mBlavatarUrl); if ((site.mLocalId == mCurrentLocalId && !mIsMultiSelectEnabled) @@ -255,8 +282,6 @@ public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, if (holder.mIsSiteHidden == null || holder.mIsSiteHidden != site.mIsHidden) { holder.mIsSiteHidden = site.mIsHidden; holder.mTxtTitle.setAlpha(site.mIsHidden ? mDisabledSiteOpacity : 1f); - holder.mTxtTitle - .setTypeface(holder.mTxtTitle.getTypeface(), site.mIsHidden ? Typeface.NORMAL : Typeface.BOLD); holder.mImgBlavatar.setAlpha(site.mIsHidden ? mDisabledSiteOpacity : 1f); } diff --git a/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt b/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt index 06c4f67a3ad4..36cd06750165 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/image/ImageManager.kt @@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.target.AppWidgetTarget import com.bumptech.glide.request.target.BaseTarget import com.bumptech.glide.request.target.CustomTarget @@ -32,6 +33,7 @@ import org.wordpress.android.WordPress import org.wordpress.android.modules.GlideApp import org.wordpress.android.modules.GlideRequest import org.wordpress.android.util.AppLog +import org.wordpress.android.util.DisplayUtils import java.io.File import javax.inject.Inject import javax.inject.Singleton @@ -148,6 +150,32 @@ class ImageManager @Inject constructor(private val placeholderManager: ImagePlac .clearOnDetach() } + /** + * Loads an image from the "imgUrl" into the ImageView and applies a rounded corner transformation. Adds placeholder + * and error placeholder depending on the ImageType. + * + * If no URL is provided, it only loads the placeholder + */ + @JvmOverloads + fun loadWithRoundedCorners( + imageView: ImageView, + imageType: ImageType, + imgUrl: String = "", + cornerRadius: Int = 4, + scaleType: ScaleType = CENTER + ) { + val context = imageView.context + if (!context.isAvailable()) return + GlideApp.with(context) + .load(imgUrl) + .addFallback(imageType) + .addPlaceholder(imageType) + .applyScaleType(scaleType) + .transform(RoundedCorners(DisplayUtils.dpToPx(context, cornerRadius))) + .into(imageView) + .clearOnDetach() + } + /** * Loads an image from the "imgUrl" into the ImageView. Adds a placeholder and an error placeholder depending * on the ImageType. Attaches the ResultListener so the client can manually show/hide progress and error diff --git a/WordPress/src/main/java/org/wordpress/android/util/image/ImagePlaceholderManager.kt b/WordPress/src/main/java/org/wordpress/android/util/image/ImagePlaceholderManager.kt index 79a5d43f0b1c..1a0cda1c71b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/image/ImagePlaceholderManager.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/image/ImagePlaceholderManager.kt @@ -10,8 +10,9 @@ class ImagePlaceholderManager @Inject constructor() { return when (imgType) { ImageType.AVATAR -> R.drawable.bg_rectangle_neutral_10_user_32dp ImageType.AVATAR_WITH_BACKGROUND -> R.drawable.bg_oval_neutral_30_user_32dp - ImageType.AVATAR_WITHOUT_BACKGROUND -> R.drawable.ic_user_circle_grey_24dp + ImageType.AVATAR_WITHOUT_BACKGROUND -> R.drawable.ic_user_circle_no_padding_grey_24dp ImageType.BLAVATAR -> R.drawable.bg_rectangle_neutral_10_globe_32dp + ImageType.BLAVATAR_ROUNDED -> R.drawable.bg_rectangle_neutral_10_radius_4dp_globe_32dp ImageType.IMAGE -> null // don't display any error drawable ImageType.PHOTO -> R.color.neutral_0 ImageType.PLAN -> R.drawable.bg_oval_neutral_30_plans_32dp @@ -29,8 +30,9 @@ class ImagePlaceholderManager @Inject constructor() { return when (imgType) { ImageType.AVATAR -> R.drawable.bg_oval_neutral_0 ImageType.AVATAR_WITH_BACKGROUND -> R.drawable.bg_oval_neutral_30_user_32dp - ImageType.AVATAR_WITHOUT_BACKGROUND -> R.drawable.ic_user_circle_grey_24dp + ImageType.AVATAR_WITHOUT_BACKGROUND -> R.drawable.ic_user_circle_no_padding_grey_24dp ImageType.BLAVATAR -> R.color.neutral_0 + ImageType.BLAVATAR_ROUNDED -> R.drawable.bg_rectangle_neutral_10_radius_4dp ImageType.IMAGE -> null // don't display any placeholder ImageType.PHOTO -> R.color.neutral_0 ImageType.PLAN -> R.drawable.bg_oval_neutral_30_plans_32dp diff --git a/WordPress/src/main/java/org/wordpress/android/util/image/ImageType.kt b/WordPress/src/main/java/org/wordpress/android/util/image/ImageType.kt index 69c81b54acf3..6305457b3689 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/image/ImageType.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/image/ImageType.kt @@ -10,6 +10,7 @@ enum class ImageType { AVATAR_WITH_BACKGROUND, AVATAR_WITHOUT_BACKGROUND, BLAVATAR, + BLAVATAR_ROUNDED, IMAGE, PHOTO, PLAN, diff --git a/WordPress/src/main/res/drawable/bg_oval_surface.xml b/WordPress/src/main/res/drawable/bg_oval_surface.xml new file mode 100644 index 000000000000..e10c97565529 --- /dev/null +++ b/WordPress/src/main/res/drawable/bg_oval_surface.xml @@ -0,0 +1,5 @@ + + + + diff --git a/WordPress/src/main/res/drawable/bg_oval_white.xml b/WordPress/src/main/res/drawable/bg_oval_white.xml deleted file mode 100644 index 31548c1bcf11..000000000000 --- a/WordPress/src/main/res/drawable/bg_oval_white.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp.xml b/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp.xml new file mode 100644 index 000000000000..3b0a354e4f9d --- /dev/null +++ b/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp_globe_32dp.xml b/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp_globe_32dp.xml new file mode 100644 index 000000000000..30404da13c11 --- /dev/null +++ b/WordPress/src/main/res/drawable/bg_rectangle_neutral_10_radius_4dp_globe_32dp.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/WordPress/src/main/res/drawable/blavatar_border.xml b/WordPress/src/main/res/drawable/blavatar_border.xml deleted file mode 100644 index 96818bc142b2..000000000000 --- a/WordPress/src/main/res/drawable/blavatar_border.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/WordPress/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml b/WordPress/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml new file mode 100644 index 000000000000..f398127d5fcb --- /dev/null +++ b/WordPress/src/main/res/drawable/ic_user_circle_no_padding_grey_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/WordPress/src/main/res/drawable/ic_user_circle_white_24dp.xml b/WordPress/src/main/res/drawable/ic_user_circle_white_24dp.xml deleted file mode 100644 index df67fcdb1e83..000000000000 --- a/WordPress/src/main/res/drawable/ic_user_circle_white_24dp.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/base_site_listitem.xml b/WordPress/src/main/res/layout/base_site_listitem.xml new file mode 100644 index 000000000000..50ddda166ed3 --- /dev/null +++ b/WordPress/src/main/res/layout/base_site_listitem.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + diff --git a/WordPress/src/main/res/layout/login_epilogue_footer.xml b/WordPress/src/main/res/layout/login_epilogue_footer.xml new file mode 100644 index 000000000000..dd5e88d98ed5 --- /dev/null +++ b/WordPress/src/main/res/layout/login_epilogue_footer.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/WordPress/src/main/res/layout/login_epilogue_header.xml b/WordPress/src/main/res/layout/login_epilogue_header.xml index 9aef512e6a29..20f738532c31 100644 --- a/WordPress/src/main/res/layout/login_epilogue_header.xml +++ b/WordPress/src/main/res/layout/login_epilogue_header.xml @@ -1,77 +1,14 @@ - + - + - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/login_epilogue_screen.xml b/WordPress/src/main/res/layout/login_epilogue_screen.xml index 87b2d0d3ef28..f518162e615a 100644 --- a/WordPress/src/main/res/layout/login_epilogue_screen.xml +++ b/WordPress/src/main/res/layout/login_epilogue_screen.xml @@ -1,6 +1,5 @@ @@ -9,7 +8,7 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@+id/bottom_buttons" + android:layout_above="@+id/primary_button" android:scrollbars="vertical" android:theme="@style/LoginEpilogueSitesList" /> @@ -26,38 +25,18 @@ android:id="@+id/bottom_shadow" android:layout_width="match_parent" android:layout_height="@dimen/button_container_shadow_height" - android:layout_above="@+id/bottom_buttons" + android:layout_above="@+id/primary_button" android:background="@drawable/login_shadow" /> - - - - - - - - - + android:layout_marginBottom="@dimen/margin_medium_large" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_medium_large" + android:text="@string/login_done" /> diff --git a/WordPress/src/main/res/layout/login_epilogue_sites_listitem.xml b/WordPress/src/main/res/layout/login_epilogue_sites_listitem.xml index bc34e03a8b06..d5d0a2c3f74d 100644 --- a/WordPress/src/main/res/layout/login_epilogue_sites_listitem.xml +++ b/WordPress/src/main/res/layout/login_epilogue_sites_listitem.xml @@ -1,49 +1,22 @@ - + android:layout_height="@dimen/site_list_item_height" + android:orientation="vertical"> - + android:layout_marginStart="@dimen/margin_extra_large" + android:layout_weight="1" /> - - - - - - + android:layout_height="@dimen/list_divider_height" + android:layout_marginStart="@dimen/margin_extra_large" + android:background="?android:attr/listDivider" /> diff --git a/WordPress/src/main/res/layout/login_include_epilogue_header.xml b/WordPress/src/main/res/layout/login_include_epilogue_header.xml new file mode 100644 index 000000000000..045879ff07b6 --- /dev/null +++ b/WordPress/src/main/res/layout/login_include_epilogue_header.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/layout/login_include_epilogue_sites_subheader.xml b/WordPress/src/main/res/layout/login_include_epilogue_sites_subheader.xml new file mode 100644 index 000000000000..7904b6edf26f --- /dev/null +++ b/WordPress/src/main/res/layout/login_include_epilogue_sites_subheader.xml @@ -0,0 +1,9 @@ + + diff --git a/WordPress/src/main/res/layout/share_intent_receiver_fragment.xml b/WordPress/src/main/res/layout/share_intent_receiver_fragment.xml new file mode 100644 index 000000000000..aeb2b68f3b27 --- /dev/null +++ b/WordPress/src/main/res/layout/share_intent_receiver_fragment.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/layout/share_intent_receiver_header.xml b/WordPress/src/main/res/layout/share_intent_receiver_header.xml new file mode 100644 index 000000000000..3ebe33835e5d --- /dev/null +++ b/WordPress/src/main/res/layout/share_intent_receiver_header.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/WordPress/src/main/res/layout/share_intent_sites_listitem.xml b/WordPress/src/main/res/layout/share_intent_sites_listitem.xml index a7275fb56b6a..6d0dad5d9321 100644 --- a/WordPress/src/main/res/layout/share_intent_sites_listitem.xml +++ b/WordPress/src/main/res/layout/share_intent_sites_listitem.xml @@ -1,31 +1,28 @@ - + android:layout_weight="1" /> - + diff --git a/WordPress/src/main/res/layout/signup_epilogue.xml b/WordPress/src/main/res/layout/signup_epilogue.xml index 650c706b6930..9d4edad28620 100644 --- a/WordPress/src/main/res/layout/signup_epilogue.xml +++ b/WordPress/src/main/res/layout/signup_epilogue.xml @@ -1,192 +1,89 @@ - - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:layout_height="0dp" + android:layout_weight="1"> - + android:layout_height="match_parent"> - + android:orientation="vertical" + android:padding="@dimen/margin_extra_large"> - + - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginTop="@dimen/margin_extra_medium_large" + android:hint="@string/signup_epilogue_hint_display" + android:imeOptions="actionDone" + android:inputType="textPersonName" /> - - - - - - - + - + + + + + + + + + - - - - - - - - - + android:layout_marginBottom="@dimen/margin_medium_large" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" + android:layout_marginTop="@dimen/margin_medium_large" + android:text="@string/login_done" /> + diff --git a/WordPress/src/main/res/layout/site_picker_listitem.xml b/WordPress/src/main/res/layout/site_picker_listitem.xml index d263b35e4524..1ebbe6e5c308 100644 --- a/WordPress/src/main/res/layout/site_picker_listitem.xml +++ b/WordPress/src/main/res/layout/site_picker_listitem.xml @@ -5,64 +5,27 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + android:layout_height="@dimen/site_list_item_height" + android:orientation="vertical"> - - - - - - - - - - - + android:layout_height="match_parent" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" /> + - diff --git a/WordPress/src/main/res/values/colors.xml b/WordPress/src/main/res/values/colors.xml index bcf6beb66388..7a682a911a25 100644 --- a/WordPress/src/main/res/values/colors.xml +++ b/WordPress/src/main/res/values/colors.xml @@ -40,6 +40,7 @@ @color/primary @color/black_translucent_20 #eff3f7 + @color/material_on_surface_disabled @color/pink_50 diff --git a/WordPress/src/main/res/values/dimens.xml b/WordPress/src/main/res/values/dimens.xml index 9c46b33aa7b3..baeae41e581b 100644 --- a/WordPress/src/main/res/values/dimens.xml +++ b/WordPress/src/main/res/values/dimens.xml @@ -263,15 +263,14 @@ @dimen/content_margin - 7dp - 15dp - 48dp 256sp 16dp 24dp @dimen/menu_item_margin_normal + 64dp + 1dp 24dp @@ -362,6 +361,7 @@ 192dp 24dp + 72dp 20dp 18dp diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 15140cc37c37..762733dac830 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2323,11 +2323,11 @@ Requesting log-in email Enter your WordPress.com password. To proceed with this Google account, please provide the matching WordPress.com password. This will be asked only once. - Connect Another Site - Connect Site - Continue + Connect another site + Connect a site + Continue + Done Already logged in to WordPress.com - \@%s Enter the address of the WordPress site you\'d like to connect. Enter the address of your WordPress site you\'d like to share the content to. Site address @@ -2345,7 +2345,6 @@ Please enter a verification code Don\'t have an account? %1$sSign up%2$s Can\'t detect your email client app - Logged in as My site My sites Log in with Google. @@ -2383,7 +2382,6 @@ There was some trouble updating your account. You can retry or revert your changes to continue. Revert Retry - New account Display Name Password (optional) You can always log in with a magic link like the one you just used, but you can also set up a password if you prefer. diff --git a/WordPress/src/main/res/values/styles.xml b/WordPress/src/main/res/values/styles.xml index d46e10810c2c..24ab12bf2db8 100644 --- a/WordPress/src/main/res/values/styles.xml +++ b/WordPress/src/main/res/values/styles.xml @@ -956,7 +956,7 @@ + + + + - -