[android][promo] promo fragment after booking is added
|
@ -153,9 +153,9 @@ Java_com_mapswithme_maps_promo_Promo_nativeGetPromoAfterBooking(JNIEnv * env, jc
|
|||
if (result.IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
jni::TScopedLocalRef promoUrl(env, jni::ToJavaString(env, result.m_promoUrl));
|
||||
jni::TScopedLocalRef pictureUrl(env, jni::ToJavaString(env, result.m_pictureUrl));
|
||||
jni::TScopedLocalRef author(env,
|
||||
env->NewObject(g_afterBooking, g_afterBookingConstructor, promoUrl.get(), pictureUrl.get()));
|
||||
auto const promoUrl = jni::ToJavaString(env, result.m_promoUrl);
|
||||
auto const pictureUrl = jni::ToJavaString(env, result.m_pictureUrl);
|
||||
|
||||
return env->NewObject(g_afterBooking, g_afterBookingConstructor, promoUrl, pictureUrl);
|
||||
}
|
||||
} // extern "C"
|
||||
|
|
BIN
android/res/drawable-hdpi/img_booking_popup_pholder_light.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
android/res/drawable-hdpi/img_booking_popup_pholder_night.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
android/res/drawable-mdpi/img_booking_popup_pholder_light.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
android/res/drawable-mdpi/img_booking_popup_pholder_night.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
android/res/drawable-xhdpi/img_booking_popup_pholder_light.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
android/res/drawable-xhdpi/img_booking_popup_pholder_night.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
android/res/drawable-xxhdpi/img_booking_popup_pholder_light.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
android/res/drawable-xxhdpi/img_booking_popup_pholder_night.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
android/res/drawable-xxxhdpi/img_booking_popup_pholder_light.png
Normal file
After Width: | Height: | Size: 123 KiB |
BIN
android/res/drawable-xxxhdpi/img_booking_popup_pholder_night.png
Normal file
After Width: | Height: | Size: 118 KiB |
56
android/res/layout/fragment_promo_after_booking_dialog.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
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/promo_after_booking_width"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/city_picture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?imgPromoBookingTitle">
|
||||
</ImageView>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/city_picture"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_base">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearanceLarge"
|
||||
android:textStyle="bold"
|
||||
android:gravity="start"
|
||||
android:text="@string/popup_booking_download_guides_title"
|
||||
tools:text="Booked a hotel?"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:text="@string/popup_booking_download_guides_message"
|
||||
tools:text="Take a look at ready-made trips around the place!"/>
|
||||
<Button
|
||||
android:id="@+id/city_guides"
|
||||
style="@style/MwmWidget.Button.Accent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/primary_button_min_height"
|
||||
android:layout_marginTop="@dimen/margin_base_plus_quarter"
|
||||
android:textAppearance="?android:textAppearanceInverse"
|
||||
android:text="@string/popup_mwm_download_guides_cta"
|
||||
tools:text="Choose one"/>
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="@style/MwmWidget.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/primary_button_min_height"
|
||||
android:layout_marginTop="@dimen/margin_half_double_plus"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:text="@string/cancel"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</android.support.v4.widget.NestedScrollView>
|
|
@ -79,6 +79,7 @@
|
|||
<attr name="bookmarkSubscriptionScreenBg" format="reference"/>
|
||||
<attr name="bookmarkSubscriptionAnnualCardEdge" format="reference"/>
|
||||
<attr name="bookmarkSubscriptionMonthlyCardEdge" format="reference"/>
|
||||
<attr name="imgPromoBookingTitle" format="reference"/>
|
||||
|
||||
<declare-styleable name="AnchorBottomSheetBehavior_Layout">
|
||||
<attr name="behavior_anchorOffset" format="dimension" />
|
||||
|
|
|
@ -263,4 +263,7 @@
|
|||
<dimen name="bookmark_purchase_img_height">258dp</dimen>
|
||||
<dimen name="bookmark_purchase_img_width">280dp</dimen>
|
||||
<dimen name="square_block_size">168dp</dimen>
|
||||
|
||||
<!-- Promo-->
|
||||
<dimen name="promo_after_booking_width">288dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -145,10 +145,15 @@
|
|||
<item name="android:textAppearanceSmall">@style/TextAppearance.Small</item>
|
||||
<item name="android:textAppearanceMedium">@style/TextAppearance.Medium</item>
|
||||
<item name="android:textAppearanceLarge">@style/TextAppearance.Large</item>
|
||||
<item name="android:textAppearanceInverse">@style/TextAppearance.Inverse</item>
|
||||
<item name="android:textAppearanceSmallInverse">@style/TextAppearance.Small.Inverse</item>
|
||||
<item name="android:textAppearanceMediumInverse">@style/TextAppearance.Medium.Inverse</item>
|
||||
<item name="android:textAppearanceLargeInverse">@style/TextAppearance.Large.Inverse</item>
|
||||
<item name="drivingOptionsViewBg">@color/light_green</item>
|
||||
<item name="bookmarkSubscriptionScreenBg">@drawable/bookmark_subscription_screen_bg</item>
|
||||
<item name="bookmarkSubscriptionAnnualCardEdge">@drawable/annual_card_edge</item>
|
||||
<item name="bookmarkSubscriptionMonthlyCardEdge">@drawable/monthly_card_edge</item>
|
||||
<item name="imgPromoBookingTitle">@drawable/img_booking_popup_pholder_light</item>
|
||||
</style>
|
||||
|
||||
<!-- Night theme -->
|
||||
|
@ -301,5 +306,6 @@
|
|||
<item name="bookmarkSubscriptionScreenBg">@drawable/bookmark_subscription_screen_bg_night</item>
|
||||
<item name="bookmarkSubscriptionAnnualCardEdge">@drawable/annual_card_edge_night</item>
|
||||
<item name="bookmarkSubscriptionMonthlyCardEdge">@drawable/monthly_card_edge_night</item>
|
||||
<item name="imgPromoBookingTitle">@drawable/img_booking_popup_pholder_night</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.support.annotation.CallSuper;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StyleRes;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
@ -75,6 +76,7 @@ import com.mapswithme.maps.news.IntroductionDialogFragment;
|
|||
import com.mapswithme.maps.news.IntroductionScreenFactory;
|
||||
import com.mapswithme.maps.promo.Promo;
|
||||
import com.mapswithme.maps.promo.PromoAfterBooking;
|
||||
import com.mapswithme.maps.promo.PromoBookingDialogFragment;
|
||||
import com.mapswithme.maps.purchase.AdsRemovalActivationCallback;
|
||||
import com.mapswithme.maps.purchase.AdsRemovalPurchaseControllerProvider;
|
||||
import com.mapswithme.maps.purchase.FailedPurchaseChecker;
|
||||
|
@ -526,7 +528,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
return;
|
||||
}
|
||||
|
||||
tryToShowAdditionalViewOnTop();
|
||||
if (savedInstanceState == null)
|
||||
tryToShowAdditionalViewOnTop();
|
||||
}
|
||||
|
||||
private void initViews(boolean isLaunchByDeeplink)
|
||||
|
@ -2210,7 +2213,17 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
if (promo == null)
|
||||
return false;
|
||||
|
||||
// Will be implemented in the next pr.
|
||||
String dialogName = PromoBookingDialogFragment.class.getName();
|
||||
if (getSupportFragmentManager().findFragmentByTag(dialogName) != null)
|
||||
return true;
|
||||
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(PromoBookingDialogFragment.EXTRA_CITY_GUIDES_URL, promo.getGuidesUrl());
|
||||
args.putString(PromoBookingDialogFragment.EXTRA_CITY_IMAGE_URL, promo.getImageUrl());
|
||||
|
||||
final DialogFragment fragment = (DialogFragment) Fragment.instantiate(this, dialogName, args);
|
||||
fragment.show(getSupportFragmentManager(), dialogName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package com.mapswithme.maps.promo;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmDialogFragment;
|
||||
import com.mapswithme.maps.bookmarks.BookmarksCatalogActivity;
|
||||
|
||||
public class PromoBookingDialogFragment extends BaseMwmDialogFragment
|
||||
{
|
||||
public static final String EXTRA_CITY_GUIDES_URL = "city_guides_url";
|
||||
public static final String EXTRA_CITY_IMAGE_URL = "city_image_url";
|
||||
|
||||
@Nullable
|
||||
private String mCityGuidesUrl;
|
||||
@Nullable
|
||||
private String mCityImageUrl;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_promo_after_booking_dialog, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStyle()
|
||||
{
|
||||
return STYLE_NO_TITLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
View cancel = view.findViewById(R.id.cancel);
|
||||
cancel.setOnClickListener(v -> dismissAllowingStateLoss());
|
||||
|
||||
if (!readArguments())
|
||||
return;
|
||||
|
||||
loadImage();
|
||||
|
||||
View cityGuides = view.findViewById(R.id.city_guides);
|
||||
cityGuides.setOnClickListener(v -> onCityGuidesClick());
|
||||
}
|
||||
|
||||
private boolean readArguments()
|
||||
{
|
||||
final Bundle arguments = getArguments();
|
||||
|
||||
if (arguments == null)
|
||||
return false;
|
||||
|
||||
mCityGuidesUrl = arguments.getString(EXTRA_CITY_GUIDES_URL);
|
||||
mCityImageUrl = arguments.getString(EXTRA_CITY_IMAGE_URL);
|
||||
|
||||
return !TextUtils.isEmpty(mCityGuidesUrl) && !TextUtils.isEmpty(mCityImageUrl);
|
||||
}
|
||||
|
||||
private void loadImage()
|
||||
{
|
||||
if (mCityImageUrl == null)
|
||||
return;
|
||||
|
||||
ImageView imageView = getViewOrThrow().findViewById(R.id.city_picture);
|
||||
Glide.with(imageView.getContext())
|
||||
.load(mCityImageUrl)
|
||||
.centerCrop()
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
private void onCityGuidesClick()
|
||||
{
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity == null || mCityGuidesUrl == null)
|
||||
return;
|
||||
|
||||
BookmarksCatalogActivity.start(activity, mCityGuidesUrl);
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
}
|
|
@ -1499,8 +1499,6 @@ void Framework::EnterForeground()
|
|||
|
||||
m_trafficManager.OnEnterForeground();
|
||||
m_routingManager.SetAllowSendingPoints(true);
|
||||
|
||||
m_promoApi->OnEnterForeground();
|
||||
}
|
||||
|
||||
void Framework::InitCountryInfoGetter()
|
||||
|
|
|
@ -45,6 +45,7 @@ UNIT_CLASS_TEST(ScopedEyeWithAsyncGuiThread, Promo_NeedToShowAfterBooking)
|
|||
{
|
||||
promo::Api api;
|
||||
Info info;
|
||||
std::string lang = "en";
|
||||
{
|
||||
MapObject poi;
|
||||
poi.SetBestType("tourism-hotel");
|
||||
|
@ -72,8 +73,7 @@ UNIT_CLASS_TEST(ScopedEyeWithAsyncGuiThread, Promo_NeedToShowAfterBooking)
|
|||
|
||||
EyeForTesting::SetInfo(info);
|
||||
settings::Set("BookingPromoAwaitingForId", kTestId);
|
||||
api.OnEnterForeground();
|
||||
TEST_EQUAL(api.NeedToShowAfterBooking(), false, ());
|
||||
TEST_EQUAL(api.GetAfterBooking(lang).IsEmpty(), false, ());
|
||||
|
||||
{
|
||||
MapObject poi;
|
||||
|
@ -97,8 +97,7 @@ UNIT_CLASS_TEST(ScopedEyeWithAsyncGuiThread, Promo_NeedToShowAfterBooking)
|
|||
info.m_promo.m_transitionToBookingTime = Clock::now() - std::chrono::hours(2);
|
||||
EyeForTesting::SetInfo(info);
|
||||
settings::Set("BookingPromoAwaitingForId", kTestId);
|
||||
api.OnEnterForeground();
|
||||
TEST_EQUAL(api.NeedToShowAfterBooking(), false, ());
|
||||
TEST_EQUAL(api.GetAfterBooking(lang).IsEmpty(), false, ());
|
||||
|
||||
{
|
||||
MapObject poi;
|
||||
|
@ -132,8 +131,7 @@ UNIT_CLASS_TEST(ScopedEyeWithAsyncGuiThread, Promo_NeedToShowAfterBooking)
|
|||
info.m_promo.m_transitionToBookingTime = Clock::now() - std::chrono::minutes(6);
|
||||
EyeForTesting::SetInfo(info);
|
||||
settings::Set("BookingPromoAwaitingForId", kTestId);
|
||||
api.OnEnterForeground();
|
||||
TEST_EQUAL(api.NeedToShowAfterBooking(), true, ());
|
||||
TEST_EQUAL(api.GetAfterBooking(lang).IsEmpty(), true, ());
|
||||
}
|
||||
|
||||
UNIT_CLASS_TEST(ScopedEyeWithAsyncGuiThread, Promo_GetCityGallery)
|
||||
|
|
|
@ -107,9 +107,18 @@ std::string GetPictureUrl(std::string const & baseUrl, std::string const & id)
|
|||
ASSERT(!baseUrl.empty(), ());
|
||||
ASSERT_EQUAL(baseUrl.back(), '/', ());
|
||||
|
||||
return baseUrl + "geoobjects/" + ToSignedId(id) + "/1/512.png";
|
||||
return baseUrl + "bookmarks_catalogue/city/" + ToSignedId(id) + ".jpg";
|
||||
}
|
||||
|
||||
std::string GetCityCatalogueUrl(std::string const & baseUrl, std::string const & id)
|
||||
{
|
||||
ASSERT(!baseUrl.empty(), ());
|
||||
ASSERT_EQUAL(baseUrl.back(), '/', ());
|
||||
|
||||
return baseUrl + "v2/mobilefront/city/" + ToSignedId(id);
|
||||
}
|
||||
|
||||
|
||||
void GetPromoCityGalleryImpl(std::string const & baseUrl, std::string const & id,
|
||||
std::string const & lang, UTM utm,
|
||||
CityGalleryCallback const & onSuccess,
|
||||
|
@ -150,6 +159,27 @@ void GetPromoCityGalleryImpl(std::string const & baseUrl, std::string const & id
|
|||
onSuccess(std::move(result));
|
||||
});
|
||||
}
|
||||
|
||||
std::string LoadPromoIdForBooking(eye::Eye::InfoType const & eyeInfo)
|
||||
{
|
||||
std::string bookingPromoAwaitingForId;
|
||||
settings::TryGet("BookingPromoAwaitingForId", bookingPromoAwaitingForId);
|
||||
|
||||
if (bookingPromoAwaitingForId.empty())
|
||||
return bookingPromoAwaitingForId;
|
||||
|
||||
auto const timeSinceLastTransitionToBooking =
|
||||
eye::Clock::now() - eyeInfo->m_promo.m_transitionToBookingTime;
|
||||
|
||||
if (timeSinceLastTransitionToBooking < kMinMinutesAfterBooking ||
|
||||
timeSinceLastTransitionToBooking > kMaxMinutesAfterBooking)
|
||||
{
|
||||
settings::Delete("BookingPromoAwaitingForId");
|
||||
bookingPromoAwaitingForId.clear();
|
||||
}
|
||||
|
||||
return bookingPromoAwaitingForId;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
|
@ -172,40 +202,17 @@ void Api::SetDelegate(std::unique_ptr<Delegate> delegate)
|
|||
m_delegate = std::move(delegate);
|
||||
}
|
||||
|
||||
void Api::OnEnterForeground()
|
||||
{
|
||||
m_bookingPromoAwaitingForId.clear();
|
||||
settings::TryGet("BookingPromoAwaitingForId", m_bookingPromoAwaitingForId);
|
||||
|
||||
if (m_bookingPromoAwaitingForId.empty())
|
||||
return;
|
||||
|
||||
auto const eyeInfo = eye::Eye::Instance().GetInfo();
|
||||
auto const timeSinceLastTransitionToBooking =
|
||||
eye::Clock::now() - eyeInfo->m_promo.m_transitionToBookingTime;
|
||||
|
||||
if (timeSinceLastTransitionToBooking < kMinMinutesAfterBooking ||
|
||||
timeSinceLastTransitionToBooking > kMaxMinutesAfterBooking)
|
||||
{
|
||||
settings::Delete("BookingPromoAwaitingForId");
|
||||
m_bookingPromoAwaitingForId.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool Api::NeedToShowAfterBooking() const
|
||||
{
|
||||
return NeedToShowImpl(m_bookingPromoAwaitingForId, eye::Eye::Instance().GetInfo());
|
||||
}
|
||||
|
||||
AfterBooking Api::GetAfterBooking(std::string const & lang) const
|
||||
{
|
||||
auto const eyeInfo = eye::Eye::Instance().GetInfo();
|
||||
|
||||
if (!NeedToShowImpl(m_bookingPromoAwaitingForId, eyeInfo))
|
||||
auto const promoId = LoadPromoIdForBooking(eyeInfo);
|
||||
|
||||
if (!NeedToShowImpl(promoId, eyeInfo))
|
||||
return {"", ""};
|
||||
|
||||
return {MakeCityGalleryUrl(m_baseUrl, m_bookingPromoAwaitingForId, lang),
|
||||
GetPictureUrl(m_basePicturesUrl, m_bookingPromoAwaitingForId)};
|
||||
return {GetCityCatalogueUrl(m_baseUrl, promoId),
|
||||
GetPictureUrl(m_basePicturesUrl, promoId)};
|
||||
}
|
||||
|
||||
std::string Api::GetPromoLinkForDownloader(std::string const & id, std::string const & lang) const
|
||||
|
@ -215,10 +222,7 @@ std::string Api::GetPromoLinkForDownloader(std::string const & id, std::string c
|
|||
|
||||
std::string Api::GetMoreUrl(std::string const & id) const
|
||||
{
|
||||
ASSERT(!m_baseUrl.empty(), ());
|
||||
ASSERT_EQUAL(m_baseUrl.back(), '/', ());
|
||||
|
||||
return m_baseUrl + "v2/mobilefront/city/" + ToSignedId(id);
|
||||
return GetCityCatalogueUrl(m_baseUrl, id);
|
||||
}
|
||||
|
||||
void Api::GetCityGallery(m2::PointD const & point, std::string const & lang, UTM utm,
|
||||
|
|
|
@ -81,8 +81,6 @@ public:
|
|||
std::string const & basePicturesUrl = PICTURES_URL);
|
||||
|
||||
void SetDelegate(std::unique_ptr<Delegate> delegate);
|
||||
void OnEnterForeground();
|
||||
bool NeedToShowAfterBooking() const;
|
||||
AfterBooking GetAfterBooking(std::string const & lang) const;
|
||||
std::string GetPromoLinkForDownloader(std::string const & id, std::string const & lang) const;
|
||||
std::string GetMoreUrl(std::string const & id) const;
|
||||
|
@ -97,6 +95,5 @@ private:
|
|||
|
||||
std::string const m_baseUrl;
|
||||
std::string const m_basePicturesUrl;
|
||||
std::string m_bookingPromoAwaitingForId;
|
||||
};
|
||||
} // namespace promo
|
||||
|
|