[android] Made architectural change regarding BaseSponsoredAdapter and his different states

BaseSponsoredAdapter was renamed to GalleryAdapter. Now,
GalleryAdapter behaviour is configured by AdapterStrategy object, it allows to avoid code duplication and make adding the new gallery and behaviour easier.
This commit is contained in:
Александр Зацепин 2017-12-02 14:57:21 +03:00 committed by Ilya Grechuhin
parent 485b4c6f3e
commit 2a0c462e54
26 changed files with 1167 additions and 869 deletions

View file

@ -1,362 +0,0 @@
package com.mapswithme.maps.base;
import android.support.annotation.CallSuper;
import android.support.annotation.IntDef;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.util.UiUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseSponsoredAdapter extends RecyclerView.Adapter<BaseSponsoredAdapter.ViewHolder>
{
private static final int MAX_ITEMS = 5;
protected static final int TYPE_PRODUCT = 0;
private static final int TYPE_MORE = 1;
protected static final int TYPE_LOADING = 2;
protected static final int TYPE_OFFLINE_MESSAGE = 3;
private static final String MORE = MwmApplication.get().getString(R.string.placepage_more_button);
private static final int TARGET_LOAD_WIDTH = UiUtils.dimen(MwmApplication.get(),
R.dimen.viator_product_width);
private static final int MARGING_QUARTER = UiUtils.dimen(MwmApplication.get(),
R.dimen.margin_quarter);
@Retention(RetentionPolicy.SOURCE)
@IntDef({ TYPE_PRODUCT, TYPE_MORE, TYPE_LOADING, TYPE_OFFLINE_MESSAGE })
protected @interface ViewType{}
@NonNull
private final List<Item> mItems;
@Nullable
private final ItemSelectedListener mListener;
public BaseSponsoredAdapter(@Nullable String url, boolean hasError,
@Nullable ItemSelectedListener listener, @ViewType int type)
{
mItems = new ArrayList<>();
mListener = listener;
mItems.add(new Item(type, getLoadingTitle(), url, getLoadingSubtitle(),
hasError, false));
}
public BaseSponsoredAdapter(@NonNull List<? extends Item> items, @Nullable String url,
@Nullable ItemSelectedListener listener, boolean shouldShowMoreItem)
{
mItems = new ArrayList<>();
mListener = listener;
boolean showMoreItem = shouldShowMoreItem && items.size() >= MAX_ITEMS;
int size = showMoreItem ? MAX_ITEMS : items.size();
for (int i = 0; i < size; i++)
{
Item product = items.get(i);
mItems.add(product);
}
if (showMoreItem)
mItems.add(new Item(TYPE_MORE, MORE, url, null, false, false));
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, @ViewType int viewType)
{
switch (viewType)
{
case TYPE_PRODUCT:
return createViewHolder(LayoutInflater.from(parent.getContext()), parent);
case TYPE_MORE:
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(getMoreLayout(), parent, false), this);
case TYPE_LOADING:
return createLoadingViewHolder(LayoutInflater.from(parent.getContext()), parent);
case TYPE_OFFLINE_MESSAGE:
return createOfflineViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.bind(mItems.get(position));
}
@Override
public int getItemCount()
{
return mItems.size();
}
@Override
@ViewType
public int getItemViewType(int position)
{
return mItems.get(position).mType;
}
public boolean containsLoading()
{
return mItems.size() == 1 && mItems.get(0).mType == TYPE_LOADING;
}
public void setLoadingError(@Nullable String url)
{
mItems.clear();
mItems.add(new Item(TYPE_LOADING, getLoadingTitle(), url, getLoadingSubtitle(),
true, false));
notifyItemChanged(0/* position */);
}
public void setLoadingCompleted(@NonNull String url)
{
mItems.clear();
mItems.add(new Item(TYPE_LOADING, getLoadingTitle(), url, getLoadingSubtitle(),
false, true));
notifyItemChanged(0/* position */);
}
@NonNull
protected abstract ViewHolder createViewHolder(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent);
@NonNull
private ViewHolder createLoadingViewHolder(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent)
{
View loadingView = inflateLoadingView(inflater, parent);
TextView moreView = (TextView) loadingView.findViewById(R.id.tv__more);
moreView.setText(getMoreLabelForLoadingView());
return new LoadingViewHolder(loadingView, this);
}
@NonNull
private ViewHolder createOfflineViewHolder(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent)
{
View offlineView = inflateOfflineView(inflater, parent);
TextView moreView = (TextView) offlineView.findViewById(R.id.tv__more);
moreView.setText(getMoreLabelForOfflineView());
return new OfflineViewHolder(offlineView, this);
}
@NonNull
protected abstract View inflateLoadingView(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent);
@NonNull
protected abstract View inflateOfflineView(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent);
@StringRes
protected abstract int getMoreLabelForLoadingView();
@StringRes
protected abstract int getMoreLabelForOfflineView();
@NonNull
protected abstract String getLoadingTitle();
@Nullable
protected abstract String getLoadingSubtitle();
@LayoutRes
protected abstract int getMoreLayout();
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener
{
@NonNull
TextView mTitle;
@NonNull
BaseSponsoredAdapter mAdapter;
protected ViewHolder(@NonNull View itemView, @NonNull BaseSponsoredAdapter adapter)
{
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.tv__title);
mAdapter = adapter;
itemView.setOnClickListener(this);
}
@CallSuper
public void bind(@NonNull Item item)
{
mTitle.setText(item.mTitle);
}
@Override
public void onClick(View v)
{
int position = getAdapterPosition();
if (position == RecyclerView.NO_POSITION)
return;
onItemSelected(mAdapter.mItems.get(position));
}
void onItemSelected(@NonNull Item item)
{
if (mAdapter.mListener == null || TextUtils.isEmpty(item.mUrl))
return;
if (item.mType == TYPE_PRODUCT)
mAdapter.mListener.onItemSelected(item.mUrl);
else if (item.mType == TYPE_MORE || item.mType == TYPE_LOADING)
mAdapter.mListener.onMoreItemSelected(item.mUrl);
}
}
public static class LoadingViewHolder extends ViewHolder
implements View.OnClickListener
{
@NonNull
ProgressBar mProgressBar;
@NonNull
TextView mSubtitle;
@NonNull
TextView mMore;
LoadingViewHolder(@NonNull View itemView, @NonNull BaseSponsoredAdapter adapter)
{
super(itemView, adapter);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.pb__progress);
mSubtitle = (TextView) itemView.findViewById(R.id.tv__subtitle);
mMore = (TextView) itemView.findViewById(R.id.tv__more);
}
@CallSuper
@Override
public void bind(@NonNull Item item)
{
super.bind(item);
UiUtils.setTextAndHideIfEmpty(mSubtitle, item.mSubtitle);
if (item.mFinished)
{
UiUtils.hide(mTitle, mSubtitle, mProgressBar);
ViewGroup.LayoutParams lp = itemView.getLayoutParams();
lp.width = TARGET_LOAD_WIDTH;
itemView.setLayoutParams(lp);
itemView.setPadding(itemView.getLeft(), itemView.getTop(),
MARGING_QUARTER, itemView.getBottom());
}
if (item.mLoadingError)
UiUtils.hide(mProgressBar);
}
@Override
public void onClick(View v)
{
int position = getAdapterPosition();
if (position == RecyclerView.NO_POSITION)
return;
onItemSelected(mAdapter.mItems.get(position));
}
void onItemSelected(@NonNull Item item)
{
if (mAdapter.mListener == null || TextUtils.isEmpty(item.mUrl))
return;
if (item.mType == TYPE_PRODUCT)
mAdapter.mListener.onItemSelected(item.mUrl);
else if (item.mType == TYPE_MORE)
mAdapter.mListener.onMoreItemSelected(item.mUrl);
else if (item.mType == TYPE_LOADING && item.mLoadingError)
mAdapter.mListener.onItemSelected(item.mUrl);
}
}
public static class OfflineViewHolder extends ViewHolder
implements View.OnClickListener
{
@NonNull
ProgressBar mProgressBar;
@NonNull
TextView mSubtitle;
@NonNull
TextView mTitle;
OfflineViewHolder(@NonNull View itemView, @NonNull BaseSponsoredAdapter adapter)
{
super(itemView, adapter);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.pb__progress);
UiUtils.hide(mProgressBar);
mTitle = (TextView) itemView.findViewById(R.id.tv__title);
mSubtitle = (TextView) itemView.findViewById(R.id.tv__subtitle);
}
@CallSuper
@Override
public void bind(@NonNull Item item)
{
super.bind(item);
UiUtils.setTextAndHideIfEmpty(mTitle, item.mTitle);
UiUtils.setTextAndHideIfEmpty(mSubtitle, item.mSubtitle);
}
@Override
public void onClick(View v)
{
int position = getAdapterPosition();
if (position == RecyclerView.NO_POSITION)
return;
onItemSelected(mAdapter.mItems.get(position));
}
void onItemSelected(@NonNull Item item)
{
if (mAdapter.mListener == null)
return;
// TODO: coming soon.
}
}
public static class Item
{
@ViewType
private final int mType;
@NonNull
private final String mTitle;
@Nullable
private final String mUrl;
@Nullable
private final String mSubtitle;
private final boolean mLoadingError;
private final boolean mFinished;
protected Item(@ViewType int type, @NonNull String title, @Nullable String url,
@Nullable String subtitle, boolean loadingError, boolean finished)
{
mType = type;
mTitle = title;
mUrl = url;
mSubtitle = subtitle;
mLoadingError = loadingError;
mFinished = finished;
}
}
public interface ItemSelectedListener
{
void onItemSelected(@NonNull String url);
void onMoreItemSelected(@NonNull String url);
}
}

View file

@ -1,155 +0,0 @@
package com.mapswithme.maps.cian;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseSponsoredAdapter;
import com.mapswithme.maps.widget.placepage.Sponsored;
import com.mapswithme.util.UiUtils;
import java.util.ArrayList;
import java.util.List;
public final class CianAdapter extends BaseSponsoredAdapter
{
private static final String LOADING_TITLE = MwmApplication
.get().getString(R.string.preloader_cian_title);
private static final String LOADING_SUBTITLE = MwmApplication
.get().getString(R.string.preloader_cian_message);
public CianAdapter(@NonNull String url, boolean hasError, @Nullable ItemSelectedListener listener)
{
super(url, hasError, listener, TYPE_LOADING);
}
public CianAdapter(@NonNull RentPlace[] items, @NonNull String url,
@Nullable ItemSelectedListener listener)
{
super(convertItems(items), url, listener, true);
}
@NonNull
private static List<Item> convertItems(@NonNull RentPlace[] items)
{
List<Item> viewItems = new ArrayList<>();
for (RentPlace place : items)
{
if (place.getOffers().isEmpty())
continue;
RentOffer product = place.getOffers().get(0);
Context context = MwmApplication.get();
String title = context.getString(R.string.room, Integer.toString(product.getRoomsCount()));
String price = Integer.toString((int) product.getPrice()) + " "
+ context.getString(R.string.rub_month);
viewItems.add(new Item(title, product.getUrl(), price, product.getAddress()));
}
return viewItems;
}
@Override
@NonNull
protected BaseSponsoredAdapter.ViewHolder createViewHolder(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent)
{
return new ProductViewHolder(inflater.inflate(R.layout.item_cian_product, parent, false),
this);
}
@NonNull
@Override
protected View inflateLoadingView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_cian_loading, parent, false);
}
@NonNull
@Override
protected View inflateOfflineView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
throw new UnsupportedOperationException("This adapter doesn't support offline mode!");
}
@Override
protected int getMoreLabelForLoadingView()
{
return R.string.preloader_cian_button;
}
@Override
protected int getMoreLabelForOfflineView()
{
throw new UnsupportedOperationException("This adapter doesn't support offline mode!");
}
@NonNull
@Override
protected String getLoadingTitle()
{
return LOADING_TITLE;
}
@Nullable
@Override
protected String getLoadingSubtitle()
{
return LOADING_SUBTITLE;
}
@LayoutRes
@Override
protected int getMoreLayout()
{
return R.layout.item_cian_more;
}
private static final class ProductViewHolder extends ViewHolder
{
@NonNull
TextView mPrice;
@NonNull
TextView mAddress;
ProductViewHolder(@NonNull View itemView, @NonNull CianAdapter adapter)
{
super(itemView, adapter);
mPrice = (TextView) itemView.findViewById(R.id.tv__price);
mAddress = (TextView) itemView.findViewById(R.id.tv__address);
}
@Override
public void bind(@NonNull BaseSponsoredAdapter.Item item)
{
super.bind(item);
Item product = (Item) item;
UiUtils.setTextAndHideIfEmpty(mPrice, product.mPrice);
UiUtils.setTextAndHideIfEmpty(mAddress, product.mAddress);
}
}
private static final class Item extends BaseSponsoredAdapter.Item
{
@NonNull
private final String mPrice;
@NonNull
private final String mAddress;
private Item(@NonNull String title, @NonNull String url, @NonNull String price,
@NonNull String address)
{
super(TYPE_PRODUCT, title, url, null, false, false);
mPrice = price;
mAddress = address;
}
}
}

View file

@ -1,29 +0,0 @@
package com.mapswithme.maps.discovery;
import android.support.annotation.NonNull;
import com.mapswithme.maps.base.BaseSponsoredAdapter;
import com.mapswithme.maps.viator.OfflineViatorAdapter;
import com.mapswithme.maps.viator.ViatorAdapter;
import com.mapswithme.maps.viator.ViatorProduct;
class DiscoveryAdapterFactory
{
@NonNull
static BaseSponsoredAdapter createViatorLoadingAdapter()
{
return new ViatorAdapter(null, false, null);
}
@NonNull
static BaseSponsoredAdapter createViatorOfflineAdapter()
{
return new OfflineViatorAdapter(null);
}
@NonNull
static BaseSponsoredAdapter createViatorAdapter(@NonNull ViatorProduct[] products)
{
return new ViatorAdapter(products, null, null, false);
}
}

View file

@ -12,7 +12,7 @@ import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmToolbarFragment;
import com.mapswithme.maps.base.BaseSponsoredAdapter;
import com.mapswithme.maps.gallery.impl.Factory;
import com.mapswithme.maps.search.SearchResult;
import com.mapswithme.maps.viator.ViatorProduct;
import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory;
@ -87,7 +87,7 @@ public class DiscoveryFragment extends BaseMwmToolbarFragment implements UICallb
if (mOnlineMode)
{
// TODO: set loading adapter for local experts here.
mThingsToDo.setAdapter(DiscoveryAdapterFactory.createViatorLoadingAdapter());
mThingsToDo.setAdapter(Factory.createViatorLoadingAdapter(null, null));
return;
}
@ -101,7 +101,7 @@ public class DiscoveryFragment extends BaseMwmToolbarFragment implements UICallb
else
{
UiUtils.show(getView(), R.id.thingsToDoLayout, R.id.thingsToDo);
mThingsToDo.setAdapter(DiscoveryAdapterFactory.createViatorOfflineAdapter());
mThingsToDo.setAdapter(Factory.createViatorOfflineAdapter(null));
}
}
@ -141,7 +141,7 @@ public class DiscoveryFragment extends BaseMwmToolbarFragment implements UICallb
public void onViatorProductsReceived(@Nullable ViatorProduct[] products)
{
if (products != null)
mThingsToDo.setAdapter(DiscoveryAdapterFactory.createViatorAdapter(products));
mThingsToDo.setAdapter(Factory.createViatorAdapter(products, null, null));
}
@MainThread
@ -157,9 +157,8 @@ public class DiscoveryFragment extends BaseMwmToolbarFragment implements UICallb
switch (type)
{
case VIATOR:
if (mThingsToDo.getAdapter() != null)
// TODO: pass cityUrl instead of null.
((BaseSponsoredAdapter) mThingsToDo.getAdapter()).setLoadingError(null);
// TODO: pass cityUrl instead of null and non-null ItemSelectedListener.
mThingsToDo.setAdapter(Factory.createViatorErrorAdapter(null, null));
break;
// TODO: processing for other adapters is coming soon.

View file

@ -0,0 +1,25 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public abstract class AdapterStrategy<VH extends Holders.BaseViewHolder<I>, I extends Items.Item>
{
@NonNull
protected final List<I> mItems = new ArrayList<>();
@NonNull
abstract VH createViewHolder(@NonNull ViewGroup parent, int viewType, @NonNull GalleryAdapter adapter);
protected abstract void onBindViewHolder(Holders.BaseViewHolder<I> holder, int position);
abstract int getItemViewType(int position);
public int getItemCount()
{
return mItems.size();
}
}

View file

@ -0,0 +1,15 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class Constants
{
static final int TYPE_PRODUCT = 0;
static final int TYPE_MORE = 1;
@Retention(RetentionPolicy.SOURCE)
@IntDef({ TYPE_PRODUCT, TYPE_MORE })
@interface ViewType{}
}

View file

@ -0,0 +1,29 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.mapswithme.maps.R;
public abstract class ErrorAdapterStrategy extends SingleItemAdapterStrategy<Holders.ErrorViewHolder>
{
protected ErrorAdapterStrategy(@Nullable String url)
{
super(url);
}
@NonNull
@Override
Holders.ErrorViewHolder createViewHolder(@NonNull ViewGroup parent, int viewType,
@NonNull GalleryAdapter adapter)
{
View errorView = inflateView(LayoutInflater.from(parent.getContext()), parent);
TextView moreView = (TextView) errorView.findViewById(R.id.tv__more);
moreView.setText(getLabelForDetailsView());
return new Holders.ErrorViewHolder(errorView, mItems, adapter);
}
}

View file

@ -0,0 +1,57 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
public class GalleryAdapter<VH extends Holders.BaseViewHolder<I>, I extends Items.Item>
extends RecyclerView.Adapter<VH>
{
@NonNull
private final AdapterStrategy<VH, I> mStrategy;
@Nullable
private ItemSelectedListener mListener;
@Nullable
public ItemSelectedListener getListener()
{
return mListener;
}
public GalleryAdapter(@NonNull AdapterStrategy<VH, I> strategy,
@Nullable ItemSelectedListener listener)
{
mStrategy = strategy;
mListener = listener;
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType)
{
return mStrategy.createViewHolder(parent, viewType, this);
}
@Override
public void onBindViewHolder(VH holder, int position)
{
mStrategy.onBindViewHolder(holder, position);
}
@Override
public int getItemCount()
{
return mStrategy.getItemCount();
}
@Override
public int getItemViewType(int position)
{
return mStrategy.getItemViewType(position);
}
public interface ItemSelectedListener
{
void onItemSelected(@NonNull String url);
void onMoreItemSelected(@NonNull String url);
}
}

View file

@ -0,0 +1,271 @@
package com.mapswithme.maps.gallery;
import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.mapswithme.maps.R;
import com.mapswithme.maps.ugc.Impress;
import com.mapswithme.maps.ugc.UGC;
import com.mapswithme.maps.widget.RatingView;
import com.mapswithme.util.UiUtils;
import java.util.List;
import static com.mapswithme.maps.gallery.Items.CianItem;
import static com.mapswithme.maps.gallery.Items.ViatorItem;
public class Holders
{
public static final class ViatorProductViewHolder
extends BaseViewHolder<ViatorItem>
{
@NonNull
ImageView mImage;
@NonNull
TextView mDuration;
@NonNull
RatingView mRating;
@NonNull
TextView mPrice;
@NonNull
Context mContext;
public ViatorProductViewHolder(@NonNull View itemView, @NonNull List<ViatorItem> items,
@NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
mContext = itemView.getContext();
mImage = (ImageView) itemView.findViewById(R.id.iv__image);
mDuration = (TextView) itemView.findViewById(R.id.tv__duration);
mRating = (RatingView) itemView.findViewById(R.id.ratingView);
mPrice = (TextView) itemView.findViewById(R.id.tv__price);
}
@Override
public void bind(@NonNull ViatorItem item)
{
super.bind(item);
if (item.mPhotoUrl != null)
{
Glide.with(mContext)
.load(item.mPhotoUrl)
.centerCrop()
.into(mImage);
}
UiUtils.setTextAndHideIfEmpty(mDuration, item.mDuration);
UiUtils.setTextAndHideIfEmpty(mPrice, mContext.getString(R.string.place_page_starting_from,
item.mPrice));
float rating = (float) item.mRating;
Impress impress = Impress.values()[UGC.nativeToImpress(rating)];
mRating.setRating(impress, String.valueOf(rating));
}
@Override
protected void onItemSelected(@NonNull ViatorItem item)
{
GalleryAdapter.ItemSelectedListener listener = mAdapter.getListener();
if (listener == null || TextUtils.isEmpty(item.getUrl()))
return;
listener.onItemSelected(item.getUrl());
}
}
public static final class ViatorMoreItemViewHolder extends BaseViewHolder<Items.ViatorItem>
{
public ViatorMoreItemViewHolder(@NonNull View itemView, @NonNull List<Items.ViatorItem> items,
@NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
}
@Override
protected void onItemSelected(@NonNull Items.ViatorItem item)
{
GalleryAdapter.ItemSelectedListener listener = mAdapter.getListener();
if (listener == null || TextUtils.isEmpty(item.getUrl()))
return;
listener.onMoreItemSelected(item.getUrl());
}
}
public static final class CianProductViewHolder extends BaseViewHolder<CianItem>
{
@NonNull
TextView mPrice;
@NonNull
TextView mAddress;
public CianProductViewHolder(@NonNull View itemView, @NonNull List<CianItem> items, @NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
mPrice = (TextView) itemView.findViewById(R.id.tv__price);
mAddress = (TextView) itemView.findViewById(R.id.tv__address);
}
@Override
public void bind(@NonNull CianItem item)
{
super.bind(item);
UiUtils.setTextAndHideIfEmpty(mPrice, item.mPrice);
UiUtils.setTextAndHideIfEmpty(mAddress, item.mAddress);
}
}
public static final class CianMoreItemViewHolder<T extends CianItem> extends BaseViewHolder<T>
{
public CianMoreItemViewHolder(@NonNull View itemView, @NonNull List<T> items,
@NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
}
@Override
protected void onItemSelected(@NonNull T item)
{
GalleryAdapter.ItemSelectedListener listener = mAdapter.getListener();
if (listener == null || TextUtils.isEmpty(item.getUrl()))
return;
listener.onMoreItemSelected(item.getUrl());
}
}
public static class BaseViewHolder<I extends Items.Item> extends RecyclerView.ViewHolder
implements View.OnClickListener
{
@NonNull
TextView mTitle;
@NonNull
protected List<I> mItems;
@NonNull
GalleryAdapter mAdapter;
protected BaseViewHolder(@NonNull View itemView, @NonNull List<I> items,
@NonNull GalleryAdapter adapter)
{
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.tv__title);
itemView.setOnClickListener(this);
mItems = items;
mAdapter = adapter;
}
@CallSuper
public void bind(@NonNull I item)
{
mTitle.setText(item.getTitle());
}
@Override
public void onClick(View v)
{
int position = getAdapterPosition();
if (position == RecyclerView.NO_POSITION || mItems.isEmpty())
return;
onItemSelected(mItems.get(position));
}
protected void onItemSelected(@NonNull I item)
{
}
}
public static class LoadingViewHolder extends BaseViewHolder<Items.Item>
implements View.OnClickListener
{
@NonNull
ProgressBar mProgressBar;
@NonNull
TextView mSubtitle;
@NonNull
TextView mMore;
LoadingViewHolder(@NonNull View itemView, @NonNull List<Items.Item> items, @NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.pb__progress);
mSubtitle = (TextView) itemView.findViewById(R.id.tv__subtitle);
mMore = (TextView) itemView.findViewById(R.id.tv__more);
}
@CallSuper
@Override
public void bind(@NonNull Items.Item item)
{
super.bind(item);
UiUtils.setTextAndHideIfEmpty(mSubtitle, item.getSubtitle());
}
@Override
public void onClick(View v)
{
int position = getAdapterPosition();
if (position == RecyclerView.NO_POSITION)
return;
onItemSelected(mItems.get(position));
}
@Override
protected void onItemSelected(@NonNull Items.Item item)
{
if (mAdapter.getListener() == null || TextUtils.isEmpty(item.getUrl()))
return;
mAdapter.getListener().onItemSelected(item.getUrl());
}
}
public static class ErrorViewHolder extends LoadingViewHolder
{
ErrorViewHolder(@NonNull View itemView, @NonNull List<Items.Item> items, @NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
UiUtils.hide(mProgressBar);
}
}
public static class OfflineViewHolder extends LoadingViewHolder
{
OfflineViewHolder(@NonNull View itemView, @NonNull List<Items.Item> items,
@NonNull GalleryAdapter adapter)
{
super(itemView, items, adapter);
UiUtils.hide(mProgressBar);
}
@CallSuper
@Override
public void bind(@NonNull Items.Item item)
{
super.bind(item);
UiUtils.setTextAndHideIfEmpty(mSubtitle, item.getSubtitle());
}
@Override
protected void onItemSelected(@NonNull Items.Item item)
{
if (mAdapter.getListener() == null)
return;
// TODO: coming soon.
}
}
}

View file

@ -0,0 +1,121 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import static com.mapswithme.maps.gallery.Constants.TYPE_MORE;
import static com.mapswithme.maps.gallery.Constants.TYPE_PRODUCT;
public class Items
{
public static class ViatorItem extends RegularAdapterStrategy.Item
{
@Nullable
final String mPhotoUrl;
@Nullable
final String mDuration;
final double mRating;
@Nullable
final String mPrice;
public ViatorItem(@Nullable String photoUrl, @NonNull String title,
@Nullable String duration, double rating, @Nullable String price,
@NonNull String url)
{
super(TYPE_PRODUCT, title, url, null);
mPhotoUrl = photoUrl;
mDuration = duration;
mRating = rating;
mPrice = price;
}
ViatorItem(@Constants.ViewType int type, @NonNull String title, @Nullable String url)
{
super(type, title, url, null);
mPhotoUrl = null;
mDuration = null;
mRating = -1;
mPrice = null;
}
}
public static class ViatorMoreItem extends ViatorItem
{
public ViatorMoreItem(@Nullable String url)
{
super(TYPE_MORE, MwmApplication.get().getString(R.string.placepage_more_button), url);
}
}
public static class CianItem extends RegularAdapterStrategy.Item
{
@NonNull
final String mPrice;
@NonNull
final String mAddress;
public CianItem(@NonNull String title, @NonNull String url, @NonNull String price,
@NonNull String address)
{
super(TYPE_PRODUCT, title, url, null);
mPrice = price;
mAddress = address;
}
CianItem(@Constants.ViewType int type, @NonNull String title, @Nullable String url)
{
super(type, title, url, null);
mPrice = "";
mAddress = "";
}
}
public static class CianMoreItem extends CianItem
{
public CianMoreItem(@Nullable String url)
{
super(TYPE_MORE, MwmApplication.get().getString(R.string.placepage_more_button), url);
}
}
public static class Item
{
@NonNull
private final String mTitle;
@Nullable
private final String mUrl;
@Nullable
private final String mSubtitle;
public Item(@NonNull String title, @Nullable String url,
@Nullable String subtitle)
{
mTitle = title;
mUrl = url;
mSubtitle = subtitle;
}
@NonNull
public String getTitle()
{
return mTitle;
}
@Nullable
public String getSubtitle()
{
return mSubtitle;
}
@Nullable
public String getUrl()
{
return mUrl;
}
}
}

View file

@ -0,0 +1,31 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.mapswithme.maps.R;
public abstract class LoadingAdapterStrategy
extends SingleItemAdapterStrategy<Holders.LoadingViewHolder>
{
protected LoadingAdapterStrategy(@Nullable String url)
{
super(url);
}
@NonNull
@Override
protected Holders.LoadingViewHolder createViewHolder(@NonNull ViewGroup parent, int viewType,
@NonNull GalleryAdapter adapter)
{
View loadingView = inflateView(LayoutInflater.from(parent.getContext()), parent);
TextView moreView = (TextView) loadingView.findViewById(R.id.tv__more);
moreView.setText(getLabelForDetailsView());
return new Holders.LoadingViewHolder(loadingView, mItems, adapter);
}
}

View file

@ -0,0 +1,34 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.mapswithme.maps.R;
public abstract class OfflineAdapterStrategy extends SingleItemAdapterStrategy<Holders.OfflineViewHolder>
{
protected OfflineAdapterStrategy(@Nullable String url)
{
super(url);
}
@NonNull
@Override
Holders.OfflineViewHolder createViewHolder(@NonNull ViewGroup parent, int viewType, @NonNull GalleryAdapter adapter)
{
View offlineView = inflateView(LayoutInflater.from(parent.getContext()), parent);
TextView moreView = (TextView) offlineView.findViewById(R.id.tv__more);
moreView.setText(getLabelForDetailsView());
return new Holders.OfflineViewHolder(offlineView, mItems, adapter);
}
@Override
protected int getLabelForDetailsView()
{
return R.string.details;
}
}

View file

@ -0,0 +1,79 @@
package com.mapswithme.maps.gallery;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.ViewGroup;
import java.util.List;
import static com.mapswithme.maps.gallery.Constants.TYPE_MORE;
import static com.mapswithme.maps.gallery.Constants.TYPE_PRODUCT;
public abstract class RegularAdapterStrategy<T extends RegularAdapterStrategy.Item>
extends AdapterStrategy<Holders.BaseViewHolder<T>, T>
{
private static final int MAX_ITEMS = 5;
public RegularAdapterStrategy(@NonNull List<T> items, @Nullable T moreItem)
{
boolean showMoreItem = moreItem != null && items.size() >= MAX_ITEMS;
int size = showMoreItem ? MAX_ITEMS : items.size();
for (int i = 0; i < size; i++)
{
T product = items.get(i);
mItems.add(product);
}
if (showMoreItem)
mItems.add(moreItem);
}
@NonNull
@Override
Holders.BaseViewHolder<T> createViewHolder(@NonNull ViewGroup parent, int viewType,
@NonNull GalleryAdapter adapter)
{
switch (viewType)
{
case TYPE_PRODUCT:
return createProductViewHodler(parent, viewType, adapter);
case TYPE_MORE:
return createMoreProductsViewHolder(parent, viewType, adapter);
default:
throw new UnsupportedOperationException("This strategy doesn't support specified view type: "
+ viewType);
}
}
@Override
protected int getItemViewType(int position)
{
return mItems.get(position).getType();
}
@NonNull
protected abstract Holders.BaseViewHolder<T> createProductViewHodler(@NonNull ViewGroup parent,
int viewType,
@NonNull GalleryAdapter adapter);
protected abstract Holders.BaseViewHolder<T> createMoreProductsViewHolder(@NonNull ViewGroup parent,
int viewType,
@NonNull GalleryAdapter adapter);
public static class Item extends Items.Item
{
@Constants.ViewType
private final int mType;
protected Item(@Constants.ViewType int type, @NonNull String title,
@Nullable String url, @Nullable String subtitle)
{
super(title, url, subtitle);
mType = type;
}
public int getType()
{
return mType;
}
}
}

View file

@ -0,0 +1,47 @@
package com.mapswithme.maps.gallery;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.MwmApplication;
abstract class SingleItemAdapterStrategy<T extends Holders.BaseViewHolder<Items.Item>>
extends AdapterStrategy<T, Items.Item>
{
SingleItemAdapterStrategy(@Nullable String url)
{
Resources res = MwmApplication.get().getResources();
mItems.add(new Items.Item(res.getString(getTitle()), url,
res.getString(getSubtitle())));
}
@StringRes
protected abstract int getTitle();
@StringRes
protected abstract int getSubtitle();
@NonNull
protected abstract View inflateView(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent);
@StringRes
protected abstract int getLabelForDetailsView();
@Override
protected void onBindViewHolder(Holders.BaseViewHolder<Items.Item> holder, int position)
{
holder.bind(mItems.get(position));
}
@Override
int getItemViewType(int position)
{
return 0;
}
}

View file

@ -0,0 +1,82 @@
package com.mapswithme.maps.gallery.impl;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.cian.RentOffer;
import com.mapswithme.maps.cian.RentPlace;
import com.mapswithme.maps.gallery.GalleryAdapter;
import com.mapswithme.maps.gallery.Holders;
import com.mapswithme.maps.gallery.Items;
import com.mapswithme.maps.gallery.RegularAdapterStrategy;
import java.util.ArrayList;
import java.util.List;
class CianAdapterStrategy extends RegularAdapterStrategy<Items.CianItem>
{
CianAdapterStrategy(@NonNull RentPlace[] items, @Nullable String moreUrl)
{
super(convertItems(items), new Items.CianMoreItem(moreUrl));
}
CianAdapterStrategy(@NonNull List<Items.CianItem> items,
@Nullable Items.CianItem moreItem)
{
super(items, moreItem);
}
@NonNull
@Override
protected Holders.BaseViewHolder<Items.CianItem> createProductViewHodler(@NonNull ViewGroup parent,
int viewType,
@NonNull GalleryAdapter adapter)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cian_product, parent,
false);
return new Holders.CianProductViewHolder(view, mItems, adapter);
}
@NonNull
@Override
protected Holders.BaseViewHolder<Items.CianItem> createMoreProductsViewHolder(@NonNull ViewGroup parent,
int viewType,
@NonNull GalleryAdapter adapter)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cian_more, parent,
false);
return new Holders.CianMoreItemViewHolder<>(view, mItems, adapter);
}
@Override
protected void onBindViewHolder(Holders.BaseViewHolder<Items.CianItem> holder, int position)
{
holder.bind(mItems.get(position));
}
@NonNull
private static List<Items.CianItem> convertItems(@NonNull RentPlace[] items)
{
List<Items.CianItem> viewItems = new ArrayList<>();
for (RentPlace place : items)
{
if (place.getOffers().isEmpty())
continue;
RentOffer product = place.getOffers().get(0);
Context context = MwmApplication.get();
String title = context.getString(R.string.room, Integer.toString(product.getRoomsCount()));
String price = Integer.toString((int) product.getPrice()) + " "
+ context.getString(R.string.rub_month);
viewItems.add(new Items.CianItem(title, product.getUrl(), price, product.getAddress()));
}
return viewItems;
}
}

View file

@ -0,0 +1,43 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.ErrorAdapterStrategy;
class CianErrorAdapterStrategy extends ErrorAdapterStrategy
{
CianErrorAdapterStrategy(@Nullable String url)
{
super(url);
}
@Override
protected int getTitle()
{
return R.string.preloader_cian_title;
}
@Override
protected int getSubtitle()
{
return R.string.preloader_cian_message;
}
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_cian_loading, parent, false);
}
@Override
protected int getLabelForDetailsView()
{
return R.string.preloader_cian_button;
}
}

View file

@ -0,0 +1,43 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.LoadingAdapterStrategy;
class CianLoadingAdapterStrategy extends LoadingAdapterStrategy
{
CianLoadingAdapterStrategy(@Nullable String url)
{
super(url);
}
@Override
protected int getTitle()
{
return R.string.preloader_cian_title;
}
@Override
protected int getSubtitle()
{
return R.string.preloader_cian_message;
}
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_cian_loading, parent, false);
}
@Override
protected int getLabelForDetailsView()
{
return R.string.preloader_cian_button;
}
}

View file

@ -0,0 +1,60 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapswithme.maps.cian.RentPlace;
import com.mapswithme.maps.gallery.GalleryAdapter;
import com.mapswithme.maps.viator.ViatorProduct;
public class Factory
{
@NonNull
public static GalleryAdapter createViatorLoadingAdapter(@Nullable String cityUrl,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new ViatorLoadingAdapterStrategy(cityUrl), listener);
}
@NonNull
public static GalleryAdapter createViatorOfflineAdapter(@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new ViatorOfflineAdapterStrategy(null), listener);
}
@NonNull
public static GalleryAdapter createViatorErrorAdapter(@Nullable String url,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new ViatorErrorAdapterStrategy(url), listener);
}
@NonNull
public static GalleryAdapter createCianLoadingAdapter(@Nullable String url,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new CianLoadingAdapterStrategy(url), listener);
}
@NonNull
public static GalleryAdapter createCianErrorAdapter(@Nullable String url,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new CianErrorAdapterStrategy(url), listener);
}
@NonNull
public static GalleryAdapter createViatorAdapter(@NonNull ViatorProduct[] products,
@Nullable String cityUrl,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new ViatorAdapterStrategy(products, cityUrl), listener);
}
@NonNull
public static GalleryAdapter createCianAdapter(@NonNull RentPlace[] products, @NonNull String url,
@Nullable GalleryAdapter.ItemSelectedListener listener)
{
return new GalleryAdapter<>(new CianAdapterStrategy(products, url), listener);
}
}

View file

@ -0,0 +1,75 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.GalleryAdapter;
import com.mapswithme.maps.gallery.Holders;
import com.mapswithme.maps.gallery.Items;
import com.mapswithme.maps.gallery.RegularAdapterStrategy;
import com.mapswithme.maps.viator.ViatorProduct;
import java.util.ArrayList;
import java.util.List;
public class ViatorAdapterStrategy
extends RegularAdapterStrategy<Items.ViatorItem>
{
ViatorAdapterStrategy(@NonNull ViatorProduct[] products, @Nullable String moreUrl)
{
super(convertItems(products), new Items.ViatorMoreItem(moreUrl));
}
public ViatorAdapterStrategy(@NonNull List<Items.ViatorItem> items,
@Nullable Items.ViatorItem moreItem)
{
super(items, moreItem);
}
@NonNull
@Override
protected Holders.BaseViewHolder<Items.ViatorItem> createProductViewHodler(@NonNull ViewGroup parent,
int viewType,
@NonNull GalleryAdapter adapter)
{
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_viator_product, parent,
false);
return new Holders.ViatorProductViewHolder(view, mItems, adapter);
}
@NonNull
@Override
protected Holders.BaseViewHolder<Items.ViatorItem> createMoreProductsViewHolder(
@NonNull ViewGroup parent, int viewType, @NonNull GalleryAdapter adapter)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_viator_more, parent,
false);
return new Holders.ViatorMoreItemViewHolder(view, mItems, adapter);
}
@Override
protected void onBindViewHolder(Holders.BaseViewHolder<Items.ViatorItem> holder, int position)
{
holder.bind(mItems.get(position));
}
@NonNull
private static List<Items.ViatorItem> convertItems(@NonNull ViatorProduct[] items)
{
List<Items.ViatorItem> viewItems = new ArrayList<>();
for (ViatorProduct product : items)
{
viewItems.add(new Items.ViatorItem(product.getPhotoUrl(), product.getTitle(),
product.getDuration(), product.getRating(), product.getPriceFormatted(),
product.getPageUrl()));
}
return viewItems;
}
}

View file

@ -0,0 +1,43 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.ErrorAdapterStrategy;
public class ViatorErrorAdapterStrategy extends ErrorAdapterStrategy
{
ViatorErrorAdapterStrategy(@Nullable String url)
{
super(url);
}
@Override
protected int getTitle()
{
return R.string.preloader_viator_title;
}
@Override
protected int getSubtitle()
{
return R.string.preloader_viator_message;
}
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_viator_loading, parent, false);
}
@Override
protected int getLabelForDetailsView()
{
return R.string.preloader_viator_button;
}
}

View file

@ -0,0 +1,43 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.LoadingAdapterStrategy;
public class ViatorLoadingAdapterStrategy extends LoadingAdapterStrategy
{
ViatorLoadingAdapterStrategy(@Nullable String url)
{
super(url);
}
@Override
protected int getTitle()
{
return R.string.preloader_viator_title;
}
@Override
protected int getSubtitle()
{
return R.string.preloader_viator_message;
}
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_viator_loading, parent, false);
}
@Override
protected int getLabelForDetailsView()
{
return R.string.preloader_viator_button;
}
}

View file

@ -0,0 +1,37 @@
package com.mapswithme.maps.gallery.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.gallery.OfflineAdapterStrategy;
public class ViatorOfflineAdapterStrategy extends OfflineAdapterStrategy
{
ViatorOfflineAdapterStrategy(@Nullable String url)
{
super(url);
}
@Override
protected int getTitle()
{
return R.string.preloader_viator_title;
}
@Override
protected int getSubtitle()
{
return R.string.common_check_internet_connection_dialog;
}
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_viator_loading, parent, false);
}
}

View file

@ -1,31 +0,0 @@
package com.mapswithme.maps.viator;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
public class OfflineViatorAdapter extends ViatorAdapter
{
public OfflineViatorAdapter(@Nullable ItemSelectedListener listener)
{
super(null, false, listener, TYPE_OFFLINE_MESSAGE);
}
@NonNull
@Override
protected String getLoadingTitle()
{
return MwmApplication
.get().getString(R.string.preloader_viator_title);
}
@Nullable
@Override
protected String getLoadingSubtitle()
{
return MwmApplication
.get().getString(R.string.common_check_internet_connection_dialog);
}
}

View file

@ -1,188 +0,0 @@
package com.mapswithme.maps.viator;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseSponsoredAdapter;
import com.mapswithme.maps.ugc.Impress;
import com.mapswithme.maps.ugc.UGC;
import com.mapswithme.maps.widget.RatingView;
import com.mapswithme.util.UiUtils;
import java.util.ArrayList;
import java.util.List;
public class ViatorAdapter extends BaseSponsoredAdapter
{
private static final String LOADING_TITLE = MwmApplication
.get().getString(R.string.preloader_viator_title);
private static final String LOADING_SUBTITLE = MwmApplication
.get().getString(R.string.preloader_viator_message);
ViatorAdapter(@Nullable String url, boolean hasError,
@Nullable ItemSelectedListener listener, @ViewType int type)
{
super(url, hasError, listener, type);
}
public ViatorAdapter(@Nullable String url, boolean hasError,
@Nullable ItemSelectedListener listener)
{
super(url, hasError, listener, TYPE_LOADING);
}
public ViatorAdapter(@NonNull ViatorProduct[] items, @Nullable String cityUrl,
@Nullable ItemSelectedListener listener, boolean shouldShowMoreItem)
{
super(convertItems(items), cityUrl, listener, shouldShowMoreItem);
}
@NonNull
private static List<Item> convertItems(@NonNull ViatorProduct[] items)
{
List<Item> viewItems = new ArrayList<>();
for (ViatorProduct product : items)
{
viewItems.add(new Item(product.getPhotoUrl(), product.getTitle(),
product.getDuration(), product.getRating(), product.getPriceFormatted(),
product.getPageUrl()));
}
return viewItems;
}
@Override
@NonNull
protected BaseSponsoredAdapter.ViewHolder createViewHolder(@NonNull LayoutInflater inflater,
@NonNull ViewGroup parent)
{
return new ProductViewHolder(inflater.inflate(R.layout.item_viator_product, parent, false),
this);
}
@NonNull
@Override
protected View inflateLoadingView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflater.inflate(R.layout.item_viator_loading, parent, false);
}
@NonNull
@Override
protected View inflateOfflineView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent)
{
return inflateLoadingView(inflater, parent);
}
@Override
protected int getMoreLabelForLoadingView()
{
return R.string.preloader_viator_button;
}
@Override
protected int getMoreLabelForOfflineView()
{
return R.string.details;
}
@NonNull
@Override
protected String getLoadingTitle()
{
return LOADING_TITLE;
}
@Nullable
@Override
protected String getLoadingSubtitle()
{
return LOADING_SUBTITLE;
}
@LayoutRes
@Override
protected int getMoreLayout()
{
return R.layout.item_viator_more;
}
private static final class ProductViewHolder extends ViewHolder
{
@NonNull
ImageView mImage;
@NonNull
TextView mDuration;
@NonNull
RatingView mRating;
@NonNull
TextView mPrice;
@NonNull
Context mContext;
ProductViewHolder(@NonNull View itemView, @NonNull ViatorAdapter adapter)
{
super(itemView, adapter);
mContext = itemView.getContext();
mImage = (ImageView) itemView.findViewById(R.id.iv__image);
mDuration = (TextView) itemView.findViewById(R.id.tv__duration);
mRating = (RatingView) itemView.findViewById(R.id.ratingView);
mPrice = (TextView) itemView.findViewById(R.id.tv__price);
}
@Override
public void bind(@NonNull BaseSponsoredAdapter.Item item)
{
super.bind(item);
Item product = (Item) item;
if (product.mPhotoUrl != null)
{
Glide.with(mContext)
.load(product.mPhotoUrl)
.centerCrop()
.into(mImage);
}
UiUtils.setTextAndHideIfEmpty(mDuration, product.mDuration);
UiUtils.setTextAndHideIfEmpty(mPrice, mContext.getString(R.string.place_page_starting_from,
product.mPrice));
float rating = (float) product.mRating;
Impress impress = Impress.values()[UGC.nativeToImpress(rating)];
mRating.setRating(impress, String.valueOf(rating));
}
}
private static final class Item extends BaseSponsoredAdapter.Item
{
@Nullable
private final String mPhotoUrl;
@Nullable
private final String mDuration;
private final double mRating;
@Nullable
private final String mPrice;
private Item(@Nullable String photoUrl, @NonNull String title,
@Nullable String duration, double rating, @Nullable String price,
@NonNull String url)
{
super(TYPE_PRODUCT, title, url, null, false, false);
mPhotoUrl = photoUrl;
mDuration = duration;
mRating = rating;
mPrice = price;
}
}
}

View file

@ -87,52 +87,52 @@ public final class ViatorProduct implements Parcelable
}
@NonNull
String getTitle()
public String getTitle()
{
return mTitle;
}
double getRating()
public double getRating()
{
return mRating;
}
int getReviewCount()
public int getReviewCount()
{
return mReviewCount;
}
@NonNull
String getDuration()
public String getDuration()
{
return mDuration;
}
double getPrice()
public double getPrice()
{
return mPrice;
}
@NonNull
String getPriceFormatted()
public String getPriceFormatted()
{
return mPriceFormatted;
}
@NonNull
String getCurrency()
public String getCurrency()
{
return mCurrency;
}
@NonNull
String getPhotoUrl()
public String getPhotoUrl()
{
return mPhotoUrl;
}
@NonNull
String getPageUrl()
public String getPageUrl()
{
return mPageUrl;
}

View file

@ -13,7 +13,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -44,10 +43,8 @@ import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.ads.CompoundNativeAdLoader;
import com.mapswithme.maps.ads.DefaultAdTracker;
import com.mapswithme.maps.ads.Factory;
import com.mapswithme.maps.ads.LocalAdInfo;
import com.mapswithme.maps.api.ParsedMwmRequest;
import com.mapswithme.maps.base.BaseSponsoredAdapter;
import com.mapswithme.maps.bookmarks.data.Bookmark;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
import com.mapswithme.maps.bookmarks.data.DistanceAndAzimut;
@ -55,7 +52,6 @@ import com.mapswithme.maps.bookmarks.data.FeatureId;
import com.mapswithme.maps.bookmarks.data.MapObject;
import com.mapswithme.maps.bookmarks.data.Metadata;
import com.mapswithme.maps.cian.Cian;
import com.mapswithme.maps.cian.CianAdapter;
import com.mapswithme.maps.cian.RentPlace;
import com.mapswithme.maps.downloader.CountryItem;
import com.mapswithme.maps.downloader.DownloaderStatusIcon;
@ -67,6 +63,7 @@ import com.mapswithme.maps.editor.data.Timetable;
import com.mapswithme.maps.gallery.FullScreenGalleryActivity;
import com.mapswithme.maps.gallery.GalleryActivity;
import com.mapswithme.maps.gallery.Image;
import com.mapswithme.maps.gallery.impl.Factory;
import com.mapswithme.maps.location.LocationHelper;
import com.mapswithme.maps.review.Review;
import com.mapswithme.maps.routing.RoutingController;
@ -74,7 +71,6 @@ import com.mapswithme.maps.taxi.TaxiManager;
import com.mapswithme.maps.ugc.Impress;
import com.mapswithme.maps.ugc.UGCController;
import com.mapswithme.maps.viator.Viator;
import com.mapswithme.maps.viator.ViatorAdapter;
import com.mapswithme.maps.viator.ViatorProduct;
import com.mapswithme.maps.widget.ArrowView;
import com.mapswithme.maps.widget.BaseShadowController;
@ -84,7 +80,6 @@ import com.mapswithme.maps.widget.RatingView;
import com.mapswithme.maps.widget.ScrollViewShadowController;
import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory;
import com.mapswithme.maps.widget.recycler.RecyclerClickListener;
import com.mapswithme.maps.widget.recycler.SingleChangeItemAnimator;
import com.mapswithme.util.ConnectionState;
import com.mapswithme.util.Graphics;
import com.mapswithme.util.NetworkPolicy;
@ -110,9 +105,9 @@ import static com.mapswithme.util.statistics.Statistics.EventName.PP_HOTEL_DESCR
import static com.mapswithme.util.statistics.Statistics.EventName.PP_HOTEL_FACILITIES;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_HOTEL_GALLERY_OPEN;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_HOTEL_REVIEWS_LAND;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_SPONSORED_ACTION;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_SPONSORED_DETAILS;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_SPONSORED_OPENTABLE;
import static com.mapswithme.util.statistics.Statistics.EventName.PP_SPONSORED_ACTION;
public class PlacePageView extends RelativeLayout
implements View.OnClickListener,
@ -126,7 +121,7 @@ public class PlacePageView extends RelativeLayout
EditBookmarkFragment.EditBookmarkListener,
BannerController.BannerListener,
Viator.ViatorListener,
BaseSponsoredAdapter.ItemSelectedListener,
com.mapswithme.maps.gallery.GalleryAdapter.ItemSelectedListener,
Cian.CianListener
{
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC);
@ -200,8 +195,6 @@ public class PlacePageView extends RelativeLayout
private View mHotelMore;
private View mSponsoredGalleryView;
private RecyclerView mRvSponsoredProducts;
@Nullable
private BaseSponsoredAdapter mSponsoredAdapter;
private TextView mTvSponsoredTitle;
private ImageView mIvSponsoredLogo;
@ -228,7 +221,7 @@ public class PlacePageView extends RelativeLayout
@NonNull
private final FacilitiesAdapter mFacilitiesAdapter = new FacilitiesAdapter();
@NonNull
private final GalleryAdapter mGalleryAdapter;
private final com.mapswithme.maps.widget.placepage.GalleryAdapter mGalleryAdapter;
@NonNull
private final NearbyAdapter mNearbyAdapter = new NearbyAdapter(this);
@NonNull
@ -303,7 +296,7 @@ public class PlacePageView extends RelativeLayout
super(context, attrs);
mIsLatLonDms = MwmApplication.prefs().getBoolean(PREF_USE_DMS, false);
mGalleryAdapter = new GalleryAdapter(context);
mGalleryAdapter = new com.mapswithme.maps.widget.placepage.GalleryAdapter(context);
mMarginBase = (int) getResources().getDimension(R.dimen.margin_base);
init(attrs, defStyleAttr);
}
@ -439,7 +432,7 @@ public class PlacePageView extends RelativeLayout
if (bannerView != null)
{
DefaultAdTracker tracker = new DefaultAdTracker();
CompoundNativeAdLoader loader = Factory.createCompoundLoader(tracker, tracker);
CompoundNativeAdLoader loader = com.mapswithme.maps.ads.Factory.createCompoundLoader(tracker, tracker);
mBannerController = new BannerController(bannerView, this, loader, tracker);
}
@ -840,15 +833,8 @@ public class PlacePageView extends RelativeLayout
@Override
public void onErrorReceived(int errorCode)
{
if (mSponsoredAdapter == null || !mSponsoredAdapter.containsLoading())
{
mSponsoredAdapter = new CianAdapter("" /* url */ , true /* hasError */, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
else
{
mSponsoredAdapter.setLoadingError(mSponsored != null ? mSponsored.getUrl() : "");
}
String url = mSponsored != null ? mSponsored.getUrl() : "";
mRvSponsoredProducts.setAdapter(Factory.createCianErrorAdapter(url, this));
Statistics.INSTANCE.trackSponsoredGalleryError(Sponsored.TYPE_CIAN, String.valueOf(errorCode));
}
@ -871,38 +857,13 @@ public class PlacePageView extends RelativeLayout
{
if (products.length == 0)
{
if (mSponsoredAdapter == null || !mSponsoredAdapter.containsLoading())
{
mSponsoredAdapter = new ViatorAdapter(cityUrl, true, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
else
{
mSponsoredAdapter.setLoadingError(cityUrl);
}
mRvSponsoredProducts.setAdapter(Factory.createViatorErrorAdapter(cityUrl, this));
Statistics.INSTANCE.trackSponsoredGalleryError(Sponsored.TYPE_VIATOR,
Statistics.ParamValue.NO_PRODUCTS);
}
else
{
if (mSponsoredAdapter == null || !mSponsoredAdapter.containsLoading())
{
mSponsoredAdapter = new ViatorAdapter(products, cityUrl, this, true);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
else
{
mRvSponsoredProducts.setItemAnimator(new SingleChangeItemAnimator() {
@Override
public void onAnimationFinished()
{
mRvSponsoredProducts.setItemAnimator(new DefaultItemAnimator());
mSponsoredAdapter = new ViatorAdapter(products, cityUrl, PlacePageView.this, true);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
});
mSponsoredAdapter.setLoadingCompleted(cityUrl);
}
mRvSponsoredProducts.setAdapter(Factory.createViatorAdapter(products, cityUrl, this));
}
}
@ -910,38 +871,13 @@ public class PlacePageView extends RelativeLayout
{
if (products.length == 0)
{
if (mSponsoredAdapter == null || !mSponsoredAdapter.containsLoading())
{
mSponsoredAdapter = new CianAdapter(url, true /* hasError */, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
else
{
mSponsoredAdapter.setLoadingError(url);
}
mRvSponsoredProducts.setAdapter(Factory.createCianErrorAdapter(url, this));
Statistics.INSTANCE.trackSponsoredGalleryError(Sponsored.TYPE_CIAN,
Statistics.ParamValue.NO_PRODUCTS);
}
else
{
if (mSponsoredAdapter == null || !mSponsoredAdapter.containsLoading())
{
mSponsoredAdapter = new CianAdapter(products, url, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
else
{
mRvSponsoredProducts.setItemAnimator(new SingleChangeItemAnimator() {
@Override
public void onAnimationFinished()
{
mRvSponsoredProducts.setItemAnimator(new DefaultItemAnimator());
mSponsoredAdapter = new CianAdapter(products, url, PlacePageView.this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
});
mSponsoredAdapter.setLoadingCompleted(url);
}
mRvSponsoredProducts.setAdapter(Factory.createCianAdapter(products, url, this));
}
}
@ -961,19 +897,13 @@ public class PlacePageView extends RelativeLayout
private void showLoadingViatorProducts(@NonNull String id, @NonNull String cityUrl)
{
if (!Viator.hasCache(id))
{
mSponsoredAdapter = new ViatorAdapter(cityUrl, false, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
mRvSponsoredProducts.setAdapter(Factory.createViatorLoadingAdapter(cityUrl, this));
}
private void showLoadingCianProducts(@NonNull FeatureId id, @NonNull String url)
{
if (!Cian.hasCache(id))
{
mSponsoredAdapter = new CianAdapter(url, false /* hasError */, this);
mRvSponsoredProducts.setAdapter(mSponsoredAdapter);
}
mRvSponsoredProducts.setAdapter(Factory.createCianLoadingAdapter(url, this));
}
private void updateGallerySponsoredTitle(@Sponsored.SponsoredType int type)
@ -989,8 +919,7 @@ public class PlacePageView extends RelativeLayout
private void clearSponsoredGalleryViews()
{
mSponsoredAdapter = null;
mRvSponsoredProducts.swapAdapter(null /* adapter */, false /* removeAndRecycleExistingViews */);
mRvSponsoredProducts.swapAdapter(null /* adapter */ , false);
}
@Override
@ -1028,8 +957,8 @@ public class PlacePageView extends RelativeLayout
Statistics.INSTANCE.trackHotelEvent(PP_HOTEL_GALLERY_OPEN, mSponsored, mMapObject);
if (position == GalleryAdapter.MAX_COUNT - 1
&& mGalleryAdapter.getItems().size() > GalleryAdapter.MAX_COUNT)
if (position == com.mapswithme.maps.widget.placepage.GalleryAdapter.MAX_COUNT - 1
&& mGalleryAdapter.getItems().size() > com.mapswithme.maps.widget.placepage.GalleryAdapter.MAX_COUNT)
{
GalleryActivity.start(getContext(), mGalleryAdapter.getItems(), mMapObject.getTitle());
}