[android][promo] promo fragment after booking is added

This commit is contained in:
Arsentiy Milchakov 2019-07-09 14:57:06 +03:00 committed by Aleksandr Zatsepin
parent ecdb7e03bb
commit f2959d7ad4
21 changed files with 219 additions and 50 deletions

View file

@ -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"

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View 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>

View file

@ -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" />

View file

@ -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>

View file

@ -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>

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -1499,8 +1499,6 @@ void Framework::EnterForeground()
m_trafficManager.OnEnterForeground();
m_routingManager.SetAllowSendingPoints(true);
m_promoApi->OnEnterForeground();
}
void Framework::InitCountryInfoGetter()

View file

@ -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)

View file

@ -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,

View file

@ -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