[android] Place Page Viator.com frame

This commit is contained in:
Roman Romanov 2017-06-21 12:32:14 +04:00 committed by Arsentiy Milchakov
parent b891f5e283
commit 494a787106
31 changed files with 813 additions and 5 deletions

View file

@ -116,6 +116,7 @@ LOCAL_SRC_FILES := \
com/mapswithme/util/statistics/PushwooshHelper.cpp \
com/mapswithme/util/LoggerFactory.cpp \
com/mapswithme/util/NetworkPolicy.cpp \
com/mapswithme/maps/viator/Viator.cpp \
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 -latomic -lz

View file

@ -560,6 +560,17 @@ uber::RideRequestLinks Framework::GetUberLinks(string const & productId, ms::Lat
return uber::Api::GetRideRequestLinks(productId, from, to);
}
void Framework::RequestViatorProducts(JNIEnv * env, jobject policy, std::string const & destId,
std::string const & currency,
viator::GetTop5ProductsCallback const & callback)
{
auto const viatorApi = m_work.GetViatorApi(ToNativeNetworkPolicy(env, policy));
if (!viatorApi)
return;
viatorApi->GetTop5Products(destId, currency, callback);
}
int Framework::ToDoAfterUpdate() const
{
return (int) m_work.ToDoAfterUpdate();

View file

@ -187,6 +187,10 @@ namespace android
uber::ErrorCallback const & errorCallback);
static uber::RideRequestLinks GetUberLinks(std::string const & productId, ms::LatLon const & from, ms::LatLon const & to);
void RequestViatorProducts(JNIEnv * env, jobject policy, std::string const & destId,
std::string const & currency,
viator::GetTop5ProductsCallback const & callback);
int ToDoAfterUpdate() const;
void LogLocalAdsEvent(local_ads::EventType event, double lat, double lon, uint16_t accuracy);

View file

@ -0,0 +1,75 @@
#include "../Framework.hpp"
#include "../../core/jni_helper.hpp"
#include "partners_api/viator_api.hpp"
namespace
{
jclass g_viatorClass;
jclass g_viatorProductClass;
jmethodID g_viatorProductConstructor;
jmethodID g_viatorCallback;
std::string g_lastRequestId;
void PrepareClassRefs(JNIEnv * env)
{
if (g_viatorClass)
return;
g_viatorClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/viator/Viator");
g_viatorProductClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/viator/ViatorProduct");
g_viatorProductConstructor =
jni::GetConstructorID(env, g_viatorProductClass,
"(Ljava/lang/String;DILjava/lang/String;DLjava/lang/String;Ljava/lang/"
"String;Ljava/lang/String;Ljava/lang/String;)V");
g_viatorCallback =
jni::GetStaticMethodID(env, g_viatorClass, "onViatorProductsReceived",
"(Ljava/lang/String;[Lcom/mapswithme/maps/viator/ViatorProduct;)V");
}
void OnViatorProductsReceived(std::string const & destId,
std::vector<viator::Product> const & products)
{
LOG(LINFO, ("Received Viator products for id = ", destId));
GetPlatform().RunOnGuiThread([=]() {
if (g_lastRequestId != destId)
return;
CHECK(!products.empty(), ("List of the products cannot be empty"));
JNIEnv * env = jni::GetEnv();
jni::TScopedLocalRef jDestId(env, jni::ToJavaString(env, destId));
jni::TScopedLocalRef jProducts(
env,
jni::ToJavaArray(env, g_viatorProductClass, products, [](JNIEnv * env,
viator::Product const & item) {
jni::TScopedLocalRef jTitle(env, jni::ToJavaString(env, item.m_title));
jni::TScopedLocalRef jDuration(env, jni::ToJavaString(env, item.m_duration));
jni::TScopedLocalRef jPriceFormatted(env, jni::ToJavaString(env, item.m_priceFormatted));
jni::TScopedLocalRef jCurrency(env, jni::ToJavaString(env, item.m_currency));
jni::TScopedLocalRef jPhotoUrl(env, jni::ToJavaString(env, item.m_photoUrl));
jni::TScopedLocalRef jPageUrl(env, jni::ToJavaString(env, item.m_pageUrl));
return env->NewObject(g_viatorProductClass, g_viatorProductConstructor, jTitle.get(),
item.m_rating, item.m_reviewCount, jDuration.get(), item.m_price,
jPriceFormatted.get(), jCurrency.get(), jPhotoUrl.get(),
jPageUrl.get());
}));
env->CallStaticVoidMethod(g_viatorClass, g_viatorCallback, jDestId.get(), jProducts.get());
});
}
} // namespace
extern "C" {
JNIEXPORT void JNICALL Java_com_mapswithme_maps_viator_Viator_nativeRequestViatorProducts(
JNIEnv * env, jclass clazz, jobject policy, jstring destId, jstring currency)
{
PrepareClassRefs(env);
g_lastRequestId = jni::ToNativeString(env, destId);
g_framework->RequestViatorProducts(env, policy, g_lastRequestId,
jni::ToNativeString(env, currency), &OnViatorProductsReceived);
}
} // extern "C"

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval"
android:height="@dimen/margin_double_plus"
android:width="@dimen/margin_double_plus">
<solid android:color="@color/base_accent"/>
</shape>
</item>
<item android:drawable="@drawable/ic_ab_right"/>
</layer-list>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval"
android:height="@dimen/margin_double_plus"
android:width="@dimen/margin_double_plus">
<solid android:color="@color/base_accent_night"/>
</shape>
</item>
<item android:drawable="@drawable/ic_ab_right"/>
</layer-list>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background"
android:drawable="@drawable/ic_star_small"/>
<item android:id="@android:id/secondaryProgress"
android:drawable="@drawable/ic_star_small_full"/>
<item android:id="@android:id/progress"
android:drawable="@drawable/ic_star_small_full"/>
</layer-list>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/viator_product_width"
android:layout_height="@dimen/viator_product_height"
android:foreground="?clickableBackground">
<ImageView
android:id="@+id/iv__image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="?viatorMore"/>
<TextView
android:id="@+id/tv__title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_half_plus"
android:layout_below="@id/iv__image"
android:layout_centerHorizontal="true"
android:textAppearance="@style/MwmTextAppearance.Body2"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:textAllCaps="true"
tools:text="More"
tools:targetApi="jelly_bean"/>
</RelativeLayout>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="@dimen/viator_product_width"
android:layout_height="@dimen/viator_product_height"
android:foreground="?clickableBackground">
<ImageView
android:id="@+id/iv__image"
android:layout_width="match_parent"
android:layout_height="@dimen/viator_product_image_height"
android:scaleType="centerCrop"
tools:src="#555555"/>
<TextView
android:id="@+id/tv__title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_half_plus"
android:layout_marginLeft="@dimen/margin_half_plus"
android:layout_marginRight="@dimen/margin_half_plus"
android:layout_below="@id/iv__image"
android:textAppearance="@style/MwmTextAppearance.Body3.Primary"
android:maxLines="3"
android:ellipsize="end"
tools:text="Statue of Liberty and Ellis Island Guided Tour"/>
<TextView
android:id="@+id/tv__duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_quarter"
android:layout_marginLeft="@dimen/margin_half_plus"
android:layout_marginRight="@dimen/margin_half_plus"
android:layout_above="@+id/rb__rate"
android:textAppearance="@style/MwmTextAppearance.Body4"
android:maxLines="1"
tools:text="4 hours"/>
<RatingBar
android:id="@id/rb__rate"
style="@style/MwmWidget.RatingBarSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_half_plus"
android:layout_marginStart="@dimen/margin_half_plus"
android:layout_marginBottom="@dimen/margin_half"
android:layout_marginTop="@dimen/margin_quarter_plus"
android:layout_alignParentBottom="true"
android:numStars="5"
android:stepSize="1"
tools:rating="3"/>
<TextView
android:id="@+id/tv__price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/margin_half"
android:layout_marginRight="@dimen/margin_half_plus"
android:layout_marginEnd="@dimen/margin_half_plus"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_toRightOf="@id/rb__rate"
android:layout_toEndOf="@id/rb__rate"
android:gravity="end"
android:textAppearance="@style/MwmTextAppearance.Body4"
android:textColor="?colorAccent"
android:maxLines="1"
android:ellipsize="end"
tools:text="$55"/>
</RelativeLayout>
</android.support.v7.widget.CardView>

View file

@ -17,6 +17,8 @@
android:layout_height="1dp"
android:layout_marginBottom="@dimen/margin_half"/>
<include layout="@layout/place_page_viator"/>
<include
layout="@layout/divider_horizontal"/>

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll__place_viator"
android:layout_width="match_parent"
android:layout_height="@dimen/viator_height"
android:orientation="vertical"
android:clipToPadding="false"
android:minHeight="@dimen/placepage_hotel_gallery_height"
android:visibility="gone"
tools:background="#20FF0000"
tools:visibility="visible">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/height_block_base"
android:paddingLeft="@dimen/margin_base"
android:paddingRight="@dimen/margin_base">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:text="Attractions and tours"
tools:targetApi="jelly_bean"/>
<TextView
android:id="@+id/btn__viator_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:textAllCaps="true"
android:text="@string/placepage_more_button"
android:background="?clickableBackground"
tools:targetApi="jelly_bean"/>
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv__viator_products"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/margin_base_plus"
tools:listitem="@layout/item_viator_product"/>
</LinearLayout>

View file

@ -198,4 +198,10 @@
<dimen name="permissions_details_width">@dimen/match_parent</dimen>
<dimen name="permissions_details_icon_size">40dp</dimen>
<dimen name="info_page_image_size">240dp</dimen>
<!-- Viator-->
<dimen name="viator_product_height">208dp</dimen>
<dimen name="viator_product_width">160dp</dimen>
<dimen name="viator_product_image_height">100dp</dimen>
<dimen name="viator_height">284dp</dimen>
</resources>

View file

@ -235,6 +235,14 @@
<item name="android:indeterminateDrawable">@drawable/rating_bar</item>
</style>
<style name="MwmWidget.RatingBarSmall" parent="android:Widget.RatingBar">
<item name="android:progressDrawable">@drawable/rating_bar_small</item>
<item name="android:indeterminateDrawable">@drawable/rating_bar_small</item>
<item name="android:minHeight">12dp</item>
<item name="android:maxHeight">12dp</item>
<item name="android:isIndicator">true</item>
</style>
<style name="MwmWidget.Counter">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>

View file

@ -84,6 +84,8 @@
<attr name="localAdSearchResBackground" format="color"/>
<attr name="tagBackground" format="reference"/>
<attr name="viatorMore" format="reference"/>
</declare-styleable>
<declare-styleable name="ThemeAttrs.NavButtons">

View file

@ -101,6 +101,8 @@
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="tagBackground">@drawable/bg_tag</item>
<item name="viatorMore">@drawable/ic_viator_more</item>
</style>
<!-- Night theme -->
@ -204,5 +206,7 @@
<item name="localAdSearchResBackground">@color/search_local_ads_customer_result_night</item>
<item name="tagBackground">@drawable/bg_tag_night</item>
<item name="viatorMore">@drawable/ic_viator_more_night</item>
</style>
</resources>

View file

@ -0,0 +1,37 @@
package com.mapswithme.maps.viator;
import android.support.annotation.NonNull;
import com.mapswithme.util.NetworkPolicy;
import java.lang.ref.WeakReference;
public final class Viator
{
@NonNull
private static WeakReference<ViatorListener> sViatorListener = new WeakReference<>(null);
public static void setViatorListener(@NonNull ViatorListener listener)
{
sViatorListener = new WeakReference<>(listener);
}
public static void onViatorProductsReceived(@NonNull String destId,
@NonNull ViatorProduct[] products)
{
ViatorListener listener = sViatorListener.get();
if (listener != null)
listener.onViatorProductsReceived(destId, products);
}
private Viator() {}
public static native void nativeRequestViatorProducts(@NonNull NetworkPolicy policy,
@NonNull String destId,
@NonNull String currency);
public interface ViatorListener
{
void onViatorProductsReceived(@NonNull String destId, @NonNull ViatorProduct[] products);
}
}

View file

@ -0,0 +1,213 @@
package com.mapswithme.maps.viator;
import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
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 final class ViatorAdapter extends RecyclerView.Adapter<ViatorAdapter.ViewHolder>
{
private static final int MAX_ITEMS = 5;
private static final int TYPE_PRODUCT = 0;
private static final int TYPE_MORE = 1;
private static final String MORE = MwmApplication.get().getString(R.string.placepage_more_button);
@Retention(RetentionPolicy.SOURCE)
@IntDef({ TYPE_PRODUCT, TYPE_MORE })
private @interface ViewType{}
@NonNull
private final List<Item> mItems;
@Nullable
private final ItemSelectedListener mListener;
public ViatorAdapter(@NonNull ViatorProduct[] items, @NonNull String cityUrl,
@Nullable ItemSelectedListener listener)
{
mItems = new ArrayList<>();
mListener = listener;
int size = items.length > MAX_ITEMS ? MAX_ITEMS : items.length;
for (int i = 0; i < size; i++)
{
ViatorProduct product = items[i];
mItems.add(new Item(TYPE_PRODUCT, product.getPhotoUrl(), product.getTitle(),
product.getDuration(), product.getRating(), product.getPriceFormatted(),
product.getPageUrl()));
}
mItems.add(new Item(TYPE_MORE, null, MORE, null, 0.0, null, cityUrl));
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, @ViewType int viewType)
{
switch (viewType)
{
case TYPE_PRODUCT:
return new ProductViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_viator_product,
parent, false), this);
case TYPE_MORE:
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_viator_more,
parent, false), this);
}
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;
}
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
@NonNull
TextView mTitle;
@NonNull
ViatorAdapter mAdapter;
ViewHolder(@NonNull View itemView, @NonNull ViatorAdapter adapter)
{
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.tv__title);
mAdapter = adapter;
itemView.setOnClickListener(this);
}
@CallSuper
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)
mAdapter.mListener.onViatorItemSelected(item.mUrl);
}
}
private static class ProductViewHolder extends ViewHolder
{
@NonNull
ImageView mImage;
@NonNull
TextView mDuration;
@NonNull
RatingBar 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 = (RatingBar) itemView.findViewById(R.id.rb__rate);
mPrice = (TextView) itemView.findViewById(R.id.tv__price);
}
@Override
void bind(@NonNull Item item)
{
super.bind(item);
if (item.mPhotoUrl != null)
{
Glide.with(mContext)
.load(item.mPhotoUrl)
.centerCrop()
.into(mImage);
}
UiUtils.visibleIf(item.mDuration != null, mDuration);
mDuration.setText(item.mDuration);
UiUtils.visibleIf(item.mPrice != null, mPrice);
mPrice.setText(item.mPrice);
mRating.setRating((float) item.mRating);
}
}
private static final class Item
{
@ViewType
private final int mType;
@Nullable
private final String mPhotoUrl;
@NonNull
private final String mTitle;
@Nullable
private final String mDuration;
private final double mRating;
@Nullable
private final String mPrice;
@NonNull
private final String mUrl;
private Item(int type, @Nullable String photoUrl, @NonNull String title,
@Nullable String duration, double rating, @Nullable String price,
@NonNull String url)
{
mType = type;
mPhotoUrl = photoUrl;
mTitle = title;
mDuration = duration;
mRating = rating;
mPrice = price;
mUrl = url;
}
}
public interface ItemSelectedListener
{
void onViatorItemSelected(@NonNull String url);
}
}

View file

@ -0,0 +1,177 @@
package com.mapswithme.maps.viator;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
public final class ViatorProduct implements Parcelable
{
@NonNull
private final String mTitle;
private final double mRating;
private final int mReviewCount;
@NonNull
private final String mDuration;
private final double mPrice;
@NonNull
private final String mPriceFormatted;
@NonNull
private final String mCurrency;
@NonNull
private final String mPhotoUrl;
@NonNull
private final String mPageUrl;
public static final Creator<ViatorProduct> CREATOR = new Creator<ViatorProduct>()
{
@Override
public ViatorProduct createFromParcel(Parcel in)
{
return new ViatorProduct(in);
}
@Override
public ViatorProduct[] newArray(int size)
{
return new ViatorProduct[size];
}
};
@SuppressWarnings("unused")
public ViatorProduct(@NonNull String title, double rating, int reviewCount,
@NonNull String duration, double price, @NonNull String priceFormatted,
@NonNull String currency, @NonNull String photoUrl, @NonNull String pageUrl)
{
mTitle = title;
mRating = rating;
mReviewCount = reviewCount;
mDuration = duration;
mPrice = price;
mPriceFormatted = priceFormatted;
mCurrency = currency;
mPhotoUrl = photoUrl;
mPageUrl = pageUrl;
}
private ViatorProduct(Parcel in)
{
mTitle = in.readString();
mRating = in.readDouble();
mReviewCount = in.readInt();
mDuration = in.readString();
mPrice = in.readDouble();
mPriceFormatted = in.readString();
mCurrency = in.readString();
mPhotoUrl = in.readString();
mPageUrl = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(mTitle);
dest.writeDouble(mRating);
dest.writeInt(mReviewCount);
dest.writeString(mDuration);
dest.writeDouble(mPrice);
dest.writeString(mPriceFormatted);
dest.writeString(mCurrency);
dest.writeString(mPhotoUrl);
dest.writeString(mPageUrl);
}
@Override
public int describeContents()
{
return 0;
}
@NonNull
String getTitle()
{
return mTitle;
}
double getRating()
{
return mRating;
}
int getReviewCount()
{
return mReviewCount;
}
@NonNull
String getDuration()
{
return mDuration;
}
double getPrice()
{
return mPrice;
}
@NonNull
String getPriceFormatted()
{
return mPriceFormatted;
}
@NonNull
String getCurrency()
{
return mCurrency;
}
@NonNull
String getPhotoUrl()
{
return mPhotoUrl;
}
@NonNull
String getPageUrl()
{
return mPageUrl;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ViatorProduct that = (ViatorProduct) o;
if (Double.compare(that.mRating, mRating) != 0) return false;
if (mReviewCount != that.mReviewCount) return false;
if (Double.compare(that.mPrice, mPrice) != 0) return false;
if (!mTitle.equals(that.mTitle)) return false;
if (!mDuration.equals(that.mDuration)) return false;
if (!mPriceFormatted.equals(that.mPriceFormatted)) return false;
if (!mCurrency.equals(that.mCurrency)) return false;
if (!mPhotoUrl.equals(that.mPhotoUrl)) return false;
return mPageUrl.equals(that.mPageUrl);
}
@Override
public int hashCode()
{
int result;
long temp;
result = mTitle.hashCode();
temp = Double.doubleToLongBits(mRating);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + mReviewCount;
result = 31 * result + mDuration.hashCode();
temp = Double.doubleToLongBits(mPrice);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + mPriceFormatted.hashCode();
result = 31 * result + mCurrency.hashCode();
result = 31 * result + mPhotoUrl.hashCode();
result = 31 * result + mPageUrl.hashCode();
return result;
}
}

View file

@ -5,6 +5,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Build;
import android.support.annotation.ColorInt;
@ -64,6 +65,9 @@ import com.mapswithme.maps.gallery.Image;
import com.mapswithme.maps.location.LocationHelper;
import com.mapswithme.maps.review.Review;
import com.mapswithme.maps.routing.RoutingController;
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;
import com.mapswithme.maps.widget.LineCountTextView;
@ -111,7 +115,9 @@ public class PlacePageView extends RelativeLayout
NearbyAdapter.OnItemClickListener,
BottomPlacePageAnimationController.OnBannerOpenListener,
EditBookmarkFragment.EditBookmarkListener,
BannerController.BannerListener
BannerController.BannerListener,
Viator.ViatorListener,
ViatorAdapter.ItemSelectedListener
{
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC);
private static final String TAG = PlacePageView.class.getSimpleName();
@ -181,6 +187,8 @@ public class PlacePageView extends RelativeLayout
private TextView mHotelRating;
private TextView mHotelRatingBase;
private View mHotelMore;
private View mViatorView;
private RecyclerView mRvViatorProducts;
@Nullable
BannerController mBannerController;
@ -402,6 +410,8 @@ public class PlacePageView extends RelativeLayout
initHotelNearbyView();
initHotelRatingView();
initViatorView();
View bannerView = findViewById(R.id.banner);
if (bannerView != null)
{
@ -599,6 +609,7 @@ public class PlacePageView extends RelativeLayout
Sponsored.setPriceListener(this);
Sponsored.setInfoListener(this);
Viator.setViatorListener(this);
}
private void initHotelRatingView()
@ -793,6 +804,47 @@ public class PlacePageView extends RelativeLayout
mHotelRatingBase.setText("");
}
@Override
public void onViatorProductsReceived(@NonNull String destId, @NonNull ViatorProduct[] products)
{
if (mSponsored != null)
updateViatorView(products, mSponsored.getUrl());
}
private void initViatorView()
{
mViatorView = findViewById(R.id.ll__place_viator);
mRvViatorProducts = (RecyclerView) mViatorView.findViewById(R.id.rv__viator_products);
mRvViatorProducts.setLayoutManager(new LinearLayoutManager(getContext(),
LinearLayoutManager.HORIZONTAL,
false));
Drawable divider = ContextCompat.getDrawable(getContext(), R.drawable.divider_transparent_half);
mRvViatorProducts.addItemDecoration(new DividerItemDecoration(divider, true));
mViatorView.findViewById(R.id.btn__viator_more).setOnClickListener(this);
}
private void updateViatorView(@NonNull ViatorProduct[] products, @NonNull String cityUrl)
{
UiUtils.showIf(products.length > 0, mViatorView);
mRvViatorProducts.setAdapter(new ViatorAdapter(products, cityUrl, this));
}
private void hideViatorViews()
{
UiUtils.hide(mViatorView);
}
private void clearViatorViews()
{
mRvViatorProducts.setAdapter(new ViatorAdapter(new ViatorProduct[]{}, "", null));
}
@Override
public void onViatorItemSelected(@NonNull String url)
{
Utils.openUrl(getContext(), url);
}
@Override
public void onLineCountCalculated(boolean grater)
{
@ -1065,14 +1117,20 @@ public class PlacePageView extends RelativeLayout
if (mMapObject != null)
{
clearHotelViews();
clearViatorViews();
if (mSponsored != null)
{
mSponsored.updateId(mMapObject);
mSponsoredPrice = mSponsored.getPrice();
String currencyCode = Utils.getCurrencyCode();
if (mSponsored.getType() == Sponsored.TYPE_BOOKING && mSponsored.getId() != null && !TextUtils.isEmpty(currencyCode))
Sponsored.requestPrice(mSponsored.getId(), currencyCode, policy);
if (mSponsored.getId() != null && !TextUtils.isEmpty(currencyCode))
{
if (mSponsored.getType() == Sponsored.TYPE_BOOKING)
Sponsored.requestPrice(mSponsored.getId(), currencyCode, policy);
else if (mSponsored.getType() == Sponsored.TYPE_VIATOR)
Viator.nativeRequestViatorProducts(policy, mSponsored.getId(), currencyCode);
}
Sponsored.requestInfo(mSponsored, Locale.getDefault().toString(), policy);
}
@ -1225,6 +1283,7 @@ public class PlacePageView extends RelativeLayout
refreshMetadataOrHide(TextUtils.isEmpty(website) ? mapObject.getMetadata(Metadata.MetadataType.FMD_URL)
: website, mWebsite, mTvWebsite);
hideHotelViews();
hideViatorViews();
}
else
{
@ -1675,6 +1734,10 @@ public class PlacePageView extends RelativeLayout
hide();
Framework.nativeDeactivatePopup();
break;
case R.id.btn__viator_more:
if (mSponsored != null)
Utils.openUrl(getContext(), mSponsored.getUrl());
break;
}
}

View file

@ -25,9 +25,10 @@ public final class Sponsored
public static final int TYPE_BOOKING = 1;
public static final int TYPE_OPENTABLE = 2;
public static final int TYPE_GEOCHAT = 3;
public static final int TYPE_VIATOR = 4;
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_NONE, TYPE_BOOKING, TYPE_OPENTABLE, TYPE_GEOCHAT})
@IntDef({TYPE_NONE, TYPE_BOOKING, TYPE_OPENTABLE, TYPE_GEOCHAT, TYPE_VIATOR})
@interface SponsoredType {}
private static class Price

View file

@ -18,6 +18,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration
@NonNull
private final Drawable mDivider;
private int mOrientation;
private final boolean mUsePaddingOnBorders;
/**
* Sole constructor. Takes in a {@link Drawable} to be used as the interior
@ -28,6 +29,20 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration
public DividerItemDecoration(@NonNull Drawable divider)
{
mDivider = divider;
mUsePaddingOnBorders = false;
}
/**
* Sole constructor. Takes in a {@link Drawable} to be used as the interior
* divider.
*
* @param divider A divider {@code Drawable} to be drawn on the RecyclerView
* @param usePaddingOnBorders A flag to use padding on borders
*/
public DividerItemDecoration(@NonNull Drawable divider, boolean usePaddingOnBorders)
{
mDivider = divider;
mUsePaddingOnBorders = usePaddingOnBorders;
}
/**
@ -61,14 +76,23 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration
{
super.getItemOffsets(outRect, view, parent, state);
if (parent.getChildAdapterPosition(view) == 0)
if (!mUsePaddingOnBorders && parent.getChildAdapterPosition(view) == 0)
return;
boolean isLastItem = parent.getChildAdapterPosition(view) == parent.getChildCount() - 1;
mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
if (mOrientation == LinearLayoutManager.HORIZONTAL)
{
outRect.left = mDivider.getIntrinsicWidth();
if (isLastItem && !mUsePaddingOnBorders)
outRect.right = mDivider.getIntrinsicWidth();
}
else if (mOrientation == LinearLayoutManager.VERTICAL)
{
outRect.top = mDivider.getIntrinsicHeight();
if (isLastItem && !mUsePaddingOnBorders)
outRect.bottom = mDivider.getIntrinsicHeight();
}
}
/**