update g1g1

This commit is contained in:
Phillip Thelen 2020-12-14 11:16:55 +01:00
parent 89fc613715
commit 86ccb5258a
92 changed files with 402 additions and 418 deletions

View file

@ -116,10 +116,6 @@
android:name=".ui.activities.GiftGemsActivity"
android:label="@string/gift_gems">
</activity>
<activity
android:name=".ui.activities.GiftOneGetOneInfoActivity"
android:label="@string/gift_one_get_one">
</activity>
<activity
android:name=".ui.activities.GuidelinesActivity"
android:label="@string/community_guidelines">

View file

@ -51,7 +51,7 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
//Crash Logging
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
implementation 'com.google.firebase:firebase-crashlytics:17.3.0'
//Dependency Injection
implementation 'com.google.dagger:dagger:2.29.1'
@ -121,8 +121,8 @@ dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
implementation 'com.plattysoft.leonids:LeonidsLib:1.3.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
@ -150,8 +150,8 @@ android {
buildConfigField "String", "TESTING_LEVEL", "\"production\""
resConfigs "en", "bg", "de", "en-rGB", "es", "fr", "hr-rHR", "in", "it", "iw", "ja", "ko", "lt", "nl", "pl", "pt-rBR", "pt-rPT", "ru", "tr", "zh", "zh-rTW"
versionCode 2663
versionName "3.1"
versionCode 2680
versionName "3.1.1"
}
buildFeatures {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#925CF3"
android:endColor="#3BCAD7"
android:angle="135"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#925CF3"
android:endColor="#3BCAD7"
android:angle="135"/>
<corners android:radius="8dp"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#925CF3"
android:endColor="#3BCAD7"
android:angle="135"/>
<corners android:radius="10dp"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/brand_400" />
<corners android:radius="@dimen/bar_radius"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

@ -1,151 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/content_background">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="30dp"
android:background="@color/content_background">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/cancel_button"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:src="@drawable/ic_close_purple_300_24dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:contentDescription="@string/cancel" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="103dp"
android:background="@drawable/layout_rounded_bg_teal"
android:layout_marginStart="@dimen/spacing_large"
android:layout_marginEnd="16dp"
android:layout_marginBottom="24dp">
<LinearLayout
android:id="@+id/contentWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="vertical"
android:gravity="center"
android:paddingStart="@dimen/spacing_large"
android:paddingEnd="@dimen/spacing_large"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gift_one_get_one"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/limited_event"
android:textColor="@color/white"
android:textAllCaps="true"
android:textSize="10sp"
style="@style/Caption2"
android:textAlignment="center"
android:maxWidth="240dp"
android:letterSpacing="0.18"
android:layout_marginBottom="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/g1g1_duration"
android:textColor="@color/white"
style="@style/Caption2"
android:textSize="15sp"
android:textAlignment="center"
android:maxWidth="240dp"/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/g1g1_promo_left"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginStart="-5dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/g1g1_promo_right"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="-5dp" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/spacing_large"
android:paddingEnd="@dimen/spacing_large"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/teal_10"
android:textStyle="bold"
android:textSize="15sp"
android:gravity="center"
android:lineHeight="20sp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:text="@string/g1g1_info_1"/>
<Button
android:id="@+id/gift_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/HabiticaButton.Purple"
android:text="@string/gift_a_subscription"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/g1g1_info_2"
android:textSize="15sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="7dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/g1g1_info_2_text"
android:gravity="center"
android:textColor="@color/text_quad"
android:lineSpacingExtra="1dp"
android:layout_marginBottom="22dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/g1g1_info_3"
android:textSize="15sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="7dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/g1g1_info_3_text"
android:gravity="center"
android:textColor="@color/text_quad"
android:lineSpacingExtra="1dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

View file

@ -120,20 +120,34 @@
android:id="@+id/gift_subscription_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/teal_50"
android:padding="@dimen/spacing_large"
android:background="@drawable/g1g1_menu_background"
android:padding="32dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/g1g1_sparkle_left" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gift_one_get_one"
android:gravity="center_horizontal"
android:textColor="@color/white"
android:textSize="16sp"
android:textSize="17sp"
android:layout_marginHorizontal="12dp"
android:fontFamily="@string/font_family_medium"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/g1g1_sparkle_right" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:text="@string/gift_one_get_one_detailed_description"
android:gravity="center_horizontal"

View file

@ -30,7 +30,7 @@
</FrameLayout>
<TextView
android:id="@+id/egg_count_view"
android:layout_width="24dp"
android:layout_width="wrap_content"
android:layout_height="24dp"
style="@style/Pill"
android:padding="0dp"
@ -72,7 +72,7 @@
</FrameLayout>
<TextView
android:id="@+id/potion_count_view"
android:layout_width="24dp"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:padding="0dp"
android:gravity="center"

View file

@ -11,44 +11,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/gift_subscription_container"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@drawable/g1g1_box"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="10dp"
android:clipChildren="true"
android:clipToPadding="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/presents1"
android:scaleType="center"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="false"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/presents2"
android:scaleType="center"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gift_one_get_one_description"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:gravity="center_horizontal"
android:textColor="@color/white"
android:textSize="16sp"
android:fontFamily="@string/font_family_medium"
android:layout_marginBottom="12dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/promo_banner"
android:layout_width="match_parent"
@ -87,6 +49,17 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
style="@style/Headline6"
android:layout_marginStart="84dp"
android:layout_marginEnd="84dp"
android:gravity="center"
android:textColor="@color/white"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_duration_view"
android:layout_width="wrap_content"

View file

@ -43,6 +43,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
style="@style/Headline6"
android:textColor="@color/white"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_subtitle_view"
android:layout_width="wrap_content"

View file

@ -142,6 +142,13 @@
android:text="@string/quest_begin"
style="@style/HabiticaButton.Yellow"
android:layout_marginEnd="16dp" />
<Button
android:id="@+id/quest_leave_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest_cancel"
style="@style/HabiticaButton.Red" />
<Button
android:id="@+id/quest_cancel_button"
@ -150,13 +157,6 @@
android:layout_height="wrap_content"
android:text="@string/quest_cancel"
style="@style/HabiticaButton.Red" />
<Button
android:id="@+id/quest_abort_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/quest_abort"
style="@style/HabiticaButton.Red" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -19,42 +19,71 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/gift_subscription_container"
android:id="@+id/promo_banner"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@drawable/g1g1_box"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="10dp"
android:clipChildren="true"
android:clipToPadding="true">
android:clipToPadding="true"
android:clickable="true"
android:visibility="gone"
tools:visibility="visible">
<ImageView
android:id="@+id/promo_banner_left_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/presents1"
android:layout_height="match_parent"
android:scaleType="center"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="false"/>
<ImageView
android:id="@+id/promo_banner_right_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/presents2"
android:layout_height="match_parent"
android:scaleType="center"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"/>
<TextView
<LinearLayout
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/promo_banner_title_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/gift_one_get_one_description"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:gravity="center_horizontal"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
style="@style/Headline6"
android:textColor="@color/white"
android:textSize="16sp"
android:fontFamily="@string/font_family_medium"
android:layout_marginBottom="12dp"
android:layout_centerInParent="true"/>
android:layout_marginStart="84dp"
android:layout_marginEnd="84dp"
android:gravity="center"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/promo_banner_duration_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Overline"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:gravity="center_horizontal"
android:textColor="@color/white"
android:textSize="16sp"
android:fontFamily="@string/font_family_medium"
android:layout_marginBottom="12dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
<LinearLayout

View file

@ -150,11 +150,6 @@
app:argType="boolean"
android:defaultValue="true" />
</activity>
<activity
android:id="@+id/giftOneGetOneInfoActivity"
android:name="com.habitrpg.android.habitica.ui.activities.GiftOneGetOneInfoActivity"
android:label="@string/gift_one_get_one" >
</activity>
<activity
android:id="@+id/gemPurchaseActivity"
android:name="com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity"

View file

@ -1128,4 +1128,8 @@
<string name="won_achievement_description"><![CDATA[<b>%s</b> selected you as the winner! Your win has been recorded in your Achievements.]]></string>
<string name="won_achievement_description_noname">You were selected as the winner! Your win has been recorded in your Achievements.</string>
<string name="claim_x_gems">Claim %d Gems</string>
<string name="g1g1_promo_info_prompt">In honor of the season of giving we\'re bringing back a very special promotion. Now when you gift somebody a subscription, you get the same sub for yourself for free!</string>
<string name="g1g1_promo_info_instructions">Tap Gift a Subscription and type in the username of the account youd like to gift to. From there, pick the sub length youd like to gift and check out. Your account will automatically be rewarded with the same level of subscription you just gifted.</string>
<string name="g1g1_promo_info_limitations">This is a limited time event that starts on %s (12:00 UTC) and will end %s (00:00 UTC). This promotion only applies when you gift to another Habitican. If you or your gift recipient already have a subscription, the gifted subscription will add months of credit that will only be used after the current subscription is cancelled or expires.</string>
<string name="gift_one_get_one_purchase_banner">Gift a sub and get a sub for free until %s</string>
</resources>

View file

@ -5,10 +5,6 @@
<key>maxChatLength</key>
<value>3000</value>
</entry>
<entry>
<key>enableGiftOneGetOne</key>
<value>false</value>
</entry>
<entry>
<key>shopSpriteSuffix</key>
</entry>

View file

@ -46,6 +46,7 @@ abstract class ContentRepositoryImpl<T : ContentLocalRepository>(localRepository
val editor = PreferenceManager.getDefaultSharedPreferences(context).edit()
editor.putString("currentEvent", it.currentEventKey)
editor.putString("currentEventPromo", it.currentEventPromo)
editor.putLong("currentEventStartDate", it.currentEventStartDate?.time ?: 0)
editor.putLong("currentEventEndDate", it.currentEventEndDate?.time ?: 0)
editor.apply()

View file

@ -1,3 +1,3 @@
package com.habitrpg.android.habitica.events
class ShowAchievementDialog(var type: String, val id: String, val isLastOnboardingAchievement: Boolean = false)
class ShowAchievementDialog(var type: String, val id: String, val message: String? = null, val text: String? = null, val isLastOnboardingAchievement: Boolean = false)

View file

@ -22,10 +22,6 @@ class AppConfigManager {
return remoteConfig.getLong("maxChatLength")
}
fun enableGiftOneGetOne(): Boolean {
return remoteConfig.getBoolean("enableGiftOneGetOne")
}
fun spriteSubstitutions(): Map<String, Map<String, String>> {
val type = object : TypeToken<Map<String, Map<String, String>>>() {}.type
return Gson().fromJson(remoteConfig.getString("spriteSubstitutions"), type)
@ -112,7 +108,7 @@ class AppConfigManager {
val startDate = if (startDateLong > 0) Date(startDateLong) else null
val endDateLong = preferences.getLong("currentEventEndDate", 0)
val endDate = if (endDateLong > 0) Date(endDateLong) else null
return getHabiticaPromotionFromKey(key, startDate, endDate)
return getHabiticaPromotionFromKey(preferences.getString("currentEventPromo", null) ?: key, startDate, endDate)
}
return null
}

View file

@ -48,7 +48,7 @@ class NotificationOpenHandler {
}
private fun openGiftOneGetOneInfoScreen() {
MainNavigationController.navigate(R.id.giftOneGetOneInfoActivity)
MainNavigationController.navigate(R.id.subscriptionPurchaseActivity)
}
private fun openQuestDetailSCreen(partyId: String?, questKey: String?) {

View file

@ -94,6 +94,8 @@ class NotificationsManager (private val context: Context) {
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> displayAchievementNotification(it)
Notification.Type.ACHIEVEMENT_BONE_COLLECTOR.type -> displayAchievementNotification(it)
Notification.Type.ACHIEVEMENT_SKELETON_CREW.type -> displayAchievementNotification(it)
Notification.Type.ACHIEVEMENT_SEEING_RED.type -> displayAchievementNotification(it)
Notification.Type.ACHIEVEMENT_RED_LETTER_DAY.type -> displayAchievementNotification(it)
Notification.Type.ACHIEVEMENT_GENERIC.type -> displayAchievementNotification(it, notifications.find { notif ->
notif.type == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type
@ -144,7 +146,8 @@ class NotificationsManager (private val context: Context) {
}
private fun displayAchievementNotification(notification: Notification, isLastOnboardingAchievement: Boolean = false): Boolean {
val achievement = (notification.data as? AchievementData)?.achievement ?: notification.type ?: ""
val data = (notification.data as? AchievementData)
val achievement = data?.achievement ?: notification.type ?: ""
val delay: Long = if (achievement == "createdTask" || achievement == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type) {
1000
} else {
@ -153,7 +156,7 @@ class NotificationsManager (private val context: Context) {
val sub = Completable.complete()
.delay(delay, TimeUnit.MILLISECONDS)
.subscribe({
EventBus.getDefault().post(ShowAchievementDialog(achievement, notification.id, isLastOnboardingAchievement))
EventBus.getDefault().post(ShowAchievementDialog(achievement, notification.id, data?.message, data?.modalText, isLastOnboardingAchievement))
}, RxErrorHandler.handleEmptyError())
logOnboardingEvents(achievement)
return true

View file

@ -47,6 +47,8 @@ class Notification {
ACHIEVEMENT_ALL_THAT_GLITTERS("ACHIEVEMENT_ALL_THAT_GLITTERS"),
ACHIEVEMENT_BONE_COLLECTOR("ACHIEVEMENT_BONE_COLLECTOR"),
ACHIEVEMENT_SKELETON_CREW("ACHIEVEMENT_SKELETON_CREW"),
ACHIEVEMENT_SEEING_RED("ACHIEVEMENT_SEEING_RED"),
ACHIEVEMENT_RED_LETTER_DAY("ACHIEVEMENT_RED_LETTER_DAY"),
FIRST_DROP("FIRST_DROPS"),
@ -78,6 +80,31 @@ class Notification {
Type.FIRST_DROP.type -> FirstDropData::class.java
Type.ACHIEVEMENT_GENERIC.type -> AchievementData::class.java
Type.WON_CHALLENGE.type -> ChallengeWonData::class.java
Type.ACHIEVEMENT_ALL_YOUR_BASE.type -> AchievementData::class.java
Type.ACHIEVEMENT_BACK_TO_BASICS.type -> AchievementData::class.java
Type.ACHIEVEMENT_JUST_ADD_WATER.type -> AchievementData::class.java
Type.ACHIEVEMENT_LOST_MASTERCLASSER.type -> AchievementData::class.java
Type.ACHIEVEMENT_MIND_OVER_MATTER.type -> AchievementData::class.java
Type.ACHIEVEMENT_DUST_DEVIL.type -> AchievementData::class.java
Type.ACHIEVEMENT_ARID_AUTHORITY.type -> AchievementData::class.java
Type.ACHIEVEMENT_MONSTER_MAGUS.type -> AchievementData::class.java
Type.ACHIEVEMENT_UNDEAD_UNDERTAKER.type -> AchievementData::class.java
Type.ACHIEVEMENT_PRIMED_FOR_PAINTING.type -> AchievementData::class.java
Type.ACHIEVEMENT_PEARLY_PRO.type -> AchievementData::class.java
Type.ACHIEVEMENT_TICKLED_PINK.type -> AchievementData::class.java
Type.ACHIEVEMENT_ROSY_OUTLOOK.type -> AchievementData::class.java
Type.ACHIEVEMENT_BUG_BONANZA.type -> AchievementData::class.java
Type.ACHIEVEMENT_BARE_NECESSITIES.type -> AchievementData::class.java
Type.ACHIEVEMENT_FRESHWATER_FRIENDS.type -> AchievementData::class.java
Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> AchievementData::class.java
Type.ACHIEVEMENT_ALL_THAT_GLITTERS.type -> AchievementData::class.java
Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> AchievementData::class.java
Type.ACHIEVEMENT_BONE_COLLECTOR.type -> AchievementData::class.java
Type.ACHIEVEMENT_SKELETON_CREW.type -> AchievementData::class.java
Type.ACHIEVEMENT_SEEING_RED.type -> AchievementData::class.java
Type.ACHIEVEMENT_RED_LETTER_DAY.type -> AchievementData::class.java
else -> null
}
}

View file

@ -12,6 +12,7 @@ class WorldState {
var rageStrikes: MutableList<QuestRageStrike>? = null
var currentEventKey: String? = null
var currentEventPromo: String? = null
var currentEventStartDate: Date? = null
var currentEventEndDate: Date? = null
}

View file

@ -3,5 +3,6 @@ package com.habitrpg.android.habitica.models.notifications
open class AchievementData : NotificationData {
var achievement: String? = null
var message: String? = null
var modalText: String? = null
}

View file

@ -9,6 +9,7 @@ import android.view.View
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding
import com.habitrpg.android.habitica.databinding.FragmentSubscriptionBinding
import com.habitrpg.android.habitica.databinding.PurchaseGemViewBinding
import com.habitrpg.android.habitica.extensions.DateUtils
import com.habitrpg.android.habitica.helpers.MainNavigationController
@ -83,6 +84,9 @@ class FallExtraGemsHabiticaPromotion(startDate: Date?, endDate: Date?) : Habitic
binding.promoBannerDurationView.setTextColor(Color.parseColor("#FEE2B6"))
}
override fun configurePurchaseBanner(binding: FragmentSubscriptionBinding) {
}
override fun configureGemView(binding: PurchaseGemViewBinding, regularAmount: Int) {
val context = binding.root.context
binding.root.background = promoBackgroundDrawable(context)

View file

@ -0,0 +1,128 @@
package com.habitrpg.android.habitica.models.promotions
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.ShapeDrawable
import android.view.View
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding
import com.habitrpg.android.habitica.databinding.FragmentSubscriptionBinding
import com.habitrpg.android.habitica.databinding.PurchaseGemViewBinding
import com.habitrpg.android.habitica.extensions.DateUtils
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.ui.fragments.PromoInfoFragment
import com.habitrpg.android.habitica.ui.fragments.purchases.SubscriptionFragment
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.promo.PromoMenuView
import java.text.SimpleDateFormat
import java.util.*
class GiftOneGetOneHabiticaPromotion(startDate: Date?, endDate: Date?) : HabiticaPromotion() {
override val identifier: String
get() = "g1g1"
override val promoType: PromoType
get() = PromoType.SUBSCRIPTION
override val startDate: Date = startDate ?: DateUtils.createDate(2020, 11, 17)
override val endDate: Date = endDate ?: DateUtils.createDate(2021, 0, 7)
override fun pillBackgroundDrawable(context: Context): Drawable {
return ContextCompat.getDrawable(context, R.drawable.g1g1_promo_pill_bg) ?: ShapeDrawable()
}
override fun backgroundColor(context: Context): Int {
return ContextCompat.getColor(context, R.color.gray_10)
}
override fun promoBackgroundDrawable(context: Context): Drawable {
return ContextCompat.getDrawable(context, R.drawable.g1g1_promo_background)
?: ShapeDrawable()
}
override fun buttonDrawable(context: Context): Drawable {
return ContextCompat.getDrawable(context, R.drawable.layout_rounded_bg_content)
?: ShapeDrawable()
}
override fun configurePromoMenuView(view: PromoMenuView) {
val context = view.context
view.background = ContextCompat.getDrawable(context, R.drawable.g1g1_menu_background)
view.setTitleText(context.getString(R.string.promo_g1g1_prompt))
view.setSubtitleText(context.getString(R.string.promo_g1g1_description))
view.setDecoration(
ContextCompat.getDrawable(context, R.drawable.g1g1_promo_menu_left),
ContextCompat.getDrawable(context, R.drawable.g1g1_promo_menu_right)
)
view.binding.button.backgroundTintList = ContextCompat.getColorStateList(context, R.color.content_background)
view.binding.button.setText(R.string.learn_more)
view.binding.button.setTextColor(ContextCompat.getColor(context, R.color.teal_100))
view.binding.button.setOnClickListener {
menuOnNavigation(context)
}
}
override fun menuOnNavigation(context: Context) {
MainNavigationController.navigate(R.id.promoInfoFragment)
}
override fun configurePurchaseBanner(binding: FragmentGemPurchaseBinding) {
val context = binding.root.context
binding.promoBanner.visibility = View.VISIBLE
binding.promoBanner.background = promoBackgroundDrawable(context)
binding.promoBannerLeftImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_left_small))
binding.promoBannerRightImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_right_small))
binding.promoBannerTitleImage.visibility = View.GONE
binding.promoBannerDurationView.visibility = View.GONE
binding.promoBannerTitleText.visibility = View.VISIBLE
val formatter = SimpleDateFormat("MMM d", Locale.getDefault())
binding.promoBannerTitleText.text = context.getString(R.string.gift_one_get_one_purchase_banner, formatter.format(endDate))
}
override fun configurePurchaseBanner(binding: FragmentSubscriptionBinding) {
val context = binding.root.context
binding.promoBanner.visibility = View.VISIBLE
binding.promoBanner.background = promoBackgroundDrawable(context)
binding.promoBannerLeftImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_left_small))
binding.promoBannerRightImage.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_right_small))
binding.promoBannerTitleImage.visibility = View.GONE
binding.promoBannerDurationView.visibility = View.GONE
binding.promoBannerTitleText.visibility = View.VISIBLE
val formatter = SimpleDateFormat("MMM d", Locale.getDefault())
binding.promoBannerTitleText.text = context.getString(R.string.gift_one_get_one_purchase_banner, formatter.format(endDate))
}
override fun configureGemView(binding: PurchaseGemViewBinding, regularAmount: Int) {
}
override fun configureInfoFragment(fragment: PromoInfoFragment) {
val context = fragment.context ?: return
fragment.binding?.promoBanner?.background = promoBackgroundDrawable(context)
fragment.binding?.promoBannerLeftImage?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_left))
fragment.binding?.promoBannerRightImage?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.g1g1_promo_right))
fragment.binding?.promoBannerTitleImage?.visibility = View.GONE
fragment.binding?.promoBannerTitleText?.visibility = View.VISIBLE
fragment.binding?.promoBannerTitleText?.text = context.getString(R.string.gift_one_get_one)
fragment.binding?.promoBannerSubtitleView?.setText(R.string.limited_event)
val formatter = SimpleDateFormat("MMM d", Locale.getDefault())
fragment.binding?.promoBannerDurationView?.text = context.getString(R.string.x_to_y,
formatter.format(startDate),
formatter.format(endDate))
fragment.binding?.promoBannerDurationView?.setTextColor(ContextCompat.getColor(context, R.color.white))
fragment.binding?.promptText?.setText(R.string.g1g1_promo_info_prompt)
fragment.binding?.promptText?.setTextColor(ContextCompat.getColor(context, R.color.text_teal))
fragment.binding?.promptButton?.background = ContextCompat.getDrawable(context, R.drawable.layout_rounded_bg_brand_400)
fragment.binding?.promptButton?.setText(R.string.gift_a_subscription)
fragment.binding?.promptButton?.setTextColor(ContextCompat.getColor(context, R.color.white))
fragment.binding?.promptButton?.setOnClickListener {
fragment.context?.let { context -> SubscriptionFragment.showGiftSubscriptionDialog(context, true) }
}
fragment.binding?.instructionDescriptionView?.text = context.getString(R.string.g1g1_promo_info_instructions)
val limitationsFormatter = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG)
fragment.binding?.limitationsDescriptionView?.text = context.getString(R.string.g1g1_promo_info_limitations, limitationsFormatter.format(startDate), limitationsFormatter.format(endDate))
}
}

View file

@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.models.promotions
import android.content.Context
import android.graphics.drawable.Drawable
import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding
import com.habitrpg.android.habitica.databinding.FragmentSubscriptionBinding
import com.habitrpg.android.habitica.databinding.PurchaseGemViewBinding
import com.habitrpg.android.habitica.ui.fragments.PromoInfoFragment
import com.habitrpg.android.habitica.ui.views.promo.PromoMenuView
@ -31,6 +32,7 @@ abstract class HabiticaPromotion {
abstract fun menuOnNavigation(context: Context)
abstract fun configurePurchaseBanner(binding: FragmentGemPurchaseBinding)
abstract fun configurePurchaseBanner(binding: FragmentSubscriptionBinding)
abstract fun configureGemView(binding: PurchaseGemViewBinding, regularAmount: Int)
abstract fun configureInfoFragment(fragment: PromoInfoFragment)
@ -40,6 +42,7 @@ fun getHabiticaPromotionFromKey(key: String, startDate: Date?, endDate: Date?):
return when (key) {
"fall_extra_gems", "fall2020", "testFall2020" -> FallExtraGemsHabiticaPromotion(startDate, endDate)
"spooky_extra_gems", "fall2020SecondPromo", "spooky2020" -> SpookyExtraGemsHabiticaPromotion(startDate, endDate)
"g1g1" -> GiftOneGetOneHabiticaPromotion(startDate, endDate)
else -> null
}
}

View file

@ -9,6 +9,7 @@ import android.view.View
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding
import com.habitrpg.android.habitica.databinding.FragmentSubscriptionBinding
import com.habitrpg.android.habitica.databinding.PurchaseGemViewBinding
import com.habitrpg.android.habitica.extensions.DateUtils
import com.habitrpg.android.habitica.helpers.MainNavigationController
@ -83,6 +84,9 @@ class SpookyExtraGemsHabiticaPromotion(startDate: Date?, endDate: Date?) : Habit
binding.promoBannerDurationView.setTextColor(ContextCompat.getColor(context, R.color.white))
}
override fun configurePurchaseBanner(binding: FragmentSubscriptionBinding) {
}
override fun configureGemView(binding: PurchaseGemViewBinding, regularAmount: Int) {
val context = binding.root.context
binding.root.background = promoBackgroundDrawable(context)

View file

@ -1,58 +0,0 @@
package com.habitrpg.android.habitica.ui.activities
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.EditText
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.databinding.ActivityGift1get1InfoBinding
import com.habitrpg.android.habitica.extensions.addCancelButton
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
class GiftOneGetOneInfoActivity : BaseActivity() {
private lateinit var binding: ActivityGift1get1InfoBinding
override fun getLayoutResId(): Int {
return R.layout.activity_gift1get1_info
}
override fun injectActivity(component: UserComponent?) {
}
override fun getContentView(): View {
binding = ActivityGift1get1InfoBinding.inflate(layoutInflater)
return binding.root
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.cancelButton.setOnClickListener {
finish()
}
binding.giftButton.setOnClickListener {
showGiftSubscriptionDialog()
}
}
private fun showGiftSubscriptionDialog() {
val chooseRecipientDialogView = layoutInflater.inflate(R.layout.dialog_choose_message_recipient, null)
val alert = HabiticaAlertDialog(this)
alert.setTitle(getString(R.string.gift_title))
alert.addButton(getString(R.string.action_continue), true) { _, _ ->
val usernameEditText = chooseRecipientDialogView?.findViewById<View>(R.id.uuidEditText) as? EditText
val intent = Intent(this, GiftSubscriptionActivity::class.java).apply {
putExtra("username", usernameEditText?.text.toString())
}
startActivity(intent)
finish()
}
alert.addCancelButton { _, _ ->
}
alert.setAdditionalContentView(chooseRecipientDialogView)
alert.show()
}
}

View file

@ -78,8 +78,6 @@ class GiftSubscriptionActivity : BaseActivity() {
selectedSubscriptionSku?.let { sku -> purchaseSubscription(sku) }
}
binding.giftSubscriptionContainer.isVisible = appConfigManager.enableGiftOneGetOne()
compositeSubscription.add(socialRepository.getMember(giftedUsername ?: giftedUserID).subscribe({
binding.avatarView.setAvatar(it)
binding.displayNameTextView.username = it.profile?.name
@ -200,7 +198,7 @@ class GiftSubscriptionActivity : BaseActivity() {
}
private fun displayConfirmationDialog() {
val message = getString(if (appConfigManager.enableGiftOneGetOne()){
val message = getString(if (appConfigManager.activePromo(this)?.identifier == "g1g1"){
R.string.gift_confirmation_text_sub_g1g1
} else {
R.string.gift_confirmation_text_sub

View file

@ -808,7 +808,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
retrieveUser(true)
val dialog = AchievementDialog(this)
dialog.isLastOnboardingAchievement = event.isLastOnboardingAchievement
dialog.setType(event.type)
dialog.setType(event.type, event.message, event.text)
dialog.enqueue()
apiClient.readNotification(event.id)
.subscribe({ }, RxErrorHandler.handleEmptyError())

View file

@ -148,7 +148,11 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler
fun bind(customization: Customization) {
this.customization = customization
DataBindingUtils.loadImage(binding.imageView, customization.getIconName(userSize, hairColor))
if (customization.type == "background" && customization.identifier == "") {
binding.imageView.setActualImageResource(R.drawable.no_background)
} else {
DataBindingUtils.loadImage(binding.imageView, customization.getIconName(userSize, hairColor))
}
if (customization.type == "background") {
val params = (binding.imageView.layoutParams as? LinearLayout.LayoutParams)?.apply {

View file

@ -10,7 +10,6 @@ import com.habitrpg.android.habitica.extensions.dpToPx
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.promotions.HabiticaPromotion
import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem
import com.habitrpg.android.habitica.ui.viewHolders.GiftOneGetOnePromoMenuView
import com.habitrpg.android.habitica.ui.views.adventureGuide.AdventureGuideMenuBanner
import com.habitrpg.android.habitica.ui.views.promo.PromoMenuView
import com.habitrpg.android.habitica.ui.views.promo.PromoMenuViewHolder
@ -115,14 +114,6 @@ class NavigationDrawerAdapter(tintColor: Int, backgroundTintColor: Int): Recycle
)
SubscriptionBuyGemsPromoViewHolder(itemView)
}
3 -> {
val itemView = GiftOneGetOnePromoMenuView(parent.context)
itemView.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
148.dpToPx(parent.context)
)
SubscriptionBuyGemsPromoViewHolder(itemView)
}
4 -> {
val itemView = AdventureGuideMenuBanner(parent.context)
itemView.layoutParams = ViewGroup.LayoutParams(

View file

@ -180,12 +180,10 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val animal = this.animal
if (animal != null) {
val color = if (animal.type == "special") animal.color else null
if (animal.numberOwned > 0) {
if (itemType == "pets") {
MainNavigationController.navigate(StableFragmentDirections.openPetDetail(animal.animal, animal.type ?: "", color))
} else {
MainNavigationController.navigate(StableFragmentDirections.openMountDetail(animal.animal, animal.type ?: "", color))
}
if (itemType == "pets") {
MainNavigationController.navigate(StableFragmentDirections.openPetDetail(animal.animal, animal.type ?: "", color))
} else {
MainNavigationController.navigate(StableFragmentDirections.openMountDetail(animal.animal, animal.type ?: "", color))
}
}
}

View file

@ -265,10 +265,6 @@ class NavigationDrawerFragment : DialogFragment() {
subscriptionItem?.subtitle = context?.getString(R.string.more_out_of_habitica)
}
if (configManager.enableGiftOneGetOne()) {
subscriptionItem?.pillText = context?.getString(R.string.sale)
context?.let { subscriptionItem?.pillBackground = ContextCompat.getDrawable(it, R.drawable.pill_bg_teal) }
}
subscriptionItem?.let { updateItem(it) }
val promoItem = getItemWithIdentifier(SIDEBAR_SUBSCRIPTION_PROMO)
@ -349,11 +345,7 @@ class NavigationDrawerFragment : DialogFragment() {
promoItem.isVisible = false
items.add(promoItem)
if (configManager.enableGiftOneGetOne()) {
val item = HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_G1G1_PROMO)
item.itemViewType = 3
items.add(item)
} else if (configManager.showSubscriptionBanner()) {
if (configManager.showSubscriptionBanner()) {
val item = HabiticaDrawerItem(R.id.subscriptionPurchaseActivity, SIDEBAR_SUBSCRIPTION_PROMO)
item.itemViewType = 2
items.add(item)

View file

@ -15,6 +15,7 @@ import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding
import com.habitrpg.android.habitica.extensions.addCancelButton
import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
import com.habitrpg.android.habitica.helpers.*
import com.habitrpg.android.habitica.models.promotions.PromoType
import com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.activities.GiftGemsActivity
@ -58,9 +59,6 @@ class GemsPurchaseFragment : BaseFragment<FragmentGemPurchaseBinding>(), GemPurc
binding?.giftGemsButton?.setOnClickListener { showGiftGemsDialog() }
binding?.giftSubscriptionContainer?.isVisible = appConfigManager.enableGiftOneGetOne()
binding?.giftSubscriptionContainer?.setOnClickListener { showGiftSubscriptionDialog() }
if (context?.isUsingNightModeResources() == true) {
binding?.headerImageView?.setImageResource(R.drawable.gem_purchase_header_dark)
}
@ -69,10 +67,12 @@ class GemsPurchaseFragment : BaseFragment<FragmentGemPurchaseBinding>(), GemPurc
if (promo != null) {
binding?.let {
promo.configurePurchaseBanner(it)
promo.configureGemView(it.gems4View.binding, 4)
promo.configureGemView(it.gems21View.binding, 21)
promo.configureGemView(it.gems42View.binding, 42)
promo.configureGemView(it.gems84View.binding, 84)
if (promo.promoType != PromoType.SUBSCRIPTION) {
promo.configureGemView(it.gems4View.binding, 4)
promo.configureGemView(it.gems21View.binding, 21)
promo.configureGemView(it.gems42View.binding, 42)
promo.configureGemView(it.gems84View.binding, 84)
}
}
binding?.promoBanner?.setOnClickListener {
val fragment = PromoInfoFragment()

View file

@ -1,12 +1,13 @@
package com.habitrpg.android.habitica.ui.fragments.purchases
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.ApiClient
@ -16,6 +17,7 @@ import com.habitrpg.android.habitica.databinding.FragmentSubscriptionBinding
import com.habitrpg.android.habitica.events.UserSubscribedEvent
import com.habitrpg.android.habitica.extensions.addCancelButton
import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
import com.habitrpg.android.habitica.extensions.layoutInflater
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.PurchaseHandler
import com.habitrpg.android.habitica.helpers.PurchaseTypes
@ -23,11 +25,10 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.activities.GiftOneGetOneInfoActivity
import com.habitrpg.android.habitica.ui.activities.GiftSubscriptionActivity
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.fragments.PromoInfoFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView
import org.greenrobot.eventbus.Subscribe
@ -76,8 +77,7 @@ class SubscriptionFragment : BaseFragment<FragmentSubscriptionBinding>(), GemPur
binding?.subscriptionDetails?.visibility = View.GONE
binding?.subscriptionDetails?.onShowSubscriptionOptions = { showSubscriptionOptions() }
binding?.giftSubscriptionContainer?.setOnClickListener { showGiftSubscriptionDialog() }
binding?.giftSubscriptionButton?.setOnClickListener { showGiftSubscriptionDialog() }
binding?.giftSubscriptionButton?.setOnClickListener { context?.let { context -> showGiftSubscriptionDialog(context, appConfigManager.activePromo(context)?.identifier == "g1g1") } }
binding?.subscription1month?.setOnPurchaseClickListener { selectSubscription(PurchaseTypes.Subscription1Month) }
binding?.subscription3month?.setOnPurchaseClickListener { selectSubscription(PurchaseTypes.Subscription3Month) }
@ -86,7 +86,21 @@ class SubscriptionFragment : BaseFragment<FragmentSubscriptionBinding>(), GemPur
binding?.subscribeButton?.setOnClickListener { subscribeUser() }
binding?.giftSubscriptionContainer?.isVisible = appConfigManager.enableGiftOneGetOne()
val promo = context?.let { appConfigManager.activePromo(it) }
if (promo != null) {
binding?.let {
promo.configurePurchaseBanner(it)
}
binding?.promoBanner?.setOnClickListener {
val fragment = PromoInfoFragment()
parentFragmentManager
.beginTransaction()
.replace(R.id.fragment_container, fragment as Fragment)
.commit()
}
} else {
binding?.promoBanner?.visibility = View.GONE
}
binding?.refreshLayout?.setOnRefreshListener { refresh() }
@ -253,29 +267,24 @@ class SubscriptionFragment : BaseFragment<FragmentSubscriptionBinding>(), GemPur
purchaseSubscription()
}
private fun showGiftSubscriptionDialog() {
if (appConfigManager.enableGiftOneGetOne()) {
val intent = Intent(context, GiftOneGetOneInfoActivity::class.java)
context?.startActivity(intent)
} else {
val chooseRecipientDialogView = this.activity?.layoutInflater?.inflate(R.layout.dialog_choose_message_recipient, null)
companion object {
fun showGiftSubscriptionDialog(context: Context, iSG1G1: Boolean) {
val chooseRecipientDialogView = context.layoutInflater.inflate(R.layout.dialog_choose_message_recipient, null)
this.activity?.let { thisActivity ->
val alert = HabiticaAlertDialog(thisActivity)
alert.setTitle(getString(R.string.gift_title))
alert.addButton(getString(R.string.action_continue), true) { _, _ ->
val alert = HabiticaAlertDialog(context)
alert.setTitle(context.getString(R.string.gift_title))
alert.addButton(context.getString(R.string.action_continue), true) { _, _ ->
val usernameEditText = chooseRecipientDialogView?.findViewById<View>(R.id.uuidEditText) as? EditText
val intent = Intent(thisActivity, GiftSubscriptionActivity::class.java).apply {
val intent = Intent(context, GiftSubscriptionActivity::class.java).apply {
putExtra("username", usernameEditText?.text.toString())
}
startActivity(intent)
context.startActivity(intent)
}
alert.addCancelButton { _, _ ->
thisActivity.dismissKeyboard()
//context.dismissKeyboard()
}
alert.setAdditionalContentView(chooseRecipientDialogView)
alert.show()
}
}
}
}

View file

@ -70,7 +70,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
binding?.questRejectButton?.setOnClickListener { onQuestReject() }
binding?.questBeginButton?.setOnClickListener { onQuestBegin() }
binding?.questCancelButton?.setOnClickListener { onQuestCancel() }
binding?.questAbortButton?.setOnClickListener { onQuestAbort() }
binding?.questLeaveButton?.setOnClickListener { onQuestLeave() }
}
override fun onResume() {
@ -103,14 +103,11 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
} else if (showLeaderButtons()) {
binding?.questParticipantResponseWrapper?.visibility = View.GONE
binding?.questLeaderResponseWrapper?.visibility = View.VISIBLE
binding?.questCancelButton?.visibility = View.VISIBLE
if (isQuestActive) {
binding?.questBeginButton?.visibility = View.GONE
binding?.questCancelButton?.visibility = View.GONE
binding?.questAbortButton?.visibility = View.VISIBLE
} else {
binding?.questBeginButton?.visibility = View.VISIBLE
binding?.questCancelButton?.visibility = View.VISIBLE
binding?.questAbortButton?.visibility = View.GONE
}
} else {
binding?.questLeaderResponseWrapper?.visibility = View.GONE
@ -231,28 +228,43 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
private fun onQuestCancel() {
context?.let {
val alert = HabiticaAlertDialog(it)
alert.setMessage(R.string.quest_cancel_message)
alert.addButton(R.string.yes, true) { _, _ ->
partyId?.let { partyID ->
@Suppress("DEPRECATION")
socialRepository.cancelQuest(partyID)
.flatMap { userRepository.retrieveUser() }
.subscribe({ getActivity()?.supportFragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
if (isQuestActive) {
val builder = AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_abort_message)
.setPositiveButton(R.string.yes) { _, _ ->
partyId?.let { partyID ->
@Suppress("DEPRECATION")
socialRepository.abortQuest(partyID)
.flatMap { userRepository.retrieveUser() }
.subscribe({ getActivity()?.supportFragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
}
}.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
} else {
val alert = HabiticaAlertDialog(it)
alert.setMessage(R.string.quest_cancel_message)
alert.addButton(R.string.yes, true) { _, _ ->
partyId?.let { partyID ->
@Suppress("DEPRECATION")
socialRepository.cancelQuest(partyID)
.flatMap { userRepository.retrieveUser() }
.subscribe({ getActivity()?.supportFragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
}
}
alert.addButton(R.string.no, false)
alert.show()
}
alert.addButton(R.string.no, false)
alert.show()
}
}
private fun onQuestAbort() {
private fun onQuestLeave() {
val builder = AlertDialog.Builder(getActivity())
.setMessage(R.string.quest_abort_message)
.setPositiveButton(R.string.yes) { _, _ ->
partyId?.let { partyID ->
@Suppress("DEPRECATION")
socialRepository.abortQuest(partyID)
socialRepository.leaveQuest(partyID)
.flatMap { userRepository.retrieveUser() }
.subscribe({ getActivity()?.supportFragmentManager?.popBackStack() }, RxErrorHandler.handleEmptyError())
}

View file

@ -1,30 +0,0 @@
package com.habitrpg.android.habitica.ui.viewHolders
import android.content.Context
import android.content.Intent
import android.util.AttributeSet
import android.widget.Button
import android.widget.RelativeLayout
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.activities.GiftOneGetOneInfoActivity
class GiftOneGetOnePromoMenuView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {
init {
inflate(R.layout.promo_gift_one_get_one, true)
setBackgroundColor(ContextCompat.getColor(context, R.color.teal_50))
clipToPadding = false
clipChildren = false
clipToOutline = false
findViewById<Button>(R.id.button).setOnClickListener {
val intent = Intent(context, GiftOneGetOneInfoActivity::class.java)
context.startActivity(intent)
}
}
}

View file

@ -25,7 +25,7 @@ class AchievementDialog(context: Context) : HabiticaAlertDialog(context) {
setAdditionalContentView(binding.root)
}
fun setType(type: String) {
fun setType(type: String, message: String?, text: String?) {
when (type) {
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> configure(R.string.partyUpTitle, R.string.partyUpDescription, "partyUp")
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> configure(R.string.partyOnTitle, R.string.partyOnDescription, "partyOn")
@ -41,12 +41,17 @@ class AchievementDialog(context: Context) : HabiticaAlertDialog(context) {
"fedPet" -> configure(R.string.fedPetTitle, R.string.fedPetDescription, type)
"purchasedEquipment" -> configure(R.string.purchasedEquipmentTitle, R.string.purchasedEquipmentDescription, type)
Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type -> configure(R.string.onboardingCompleteTitle, R.string.onboardingCompleteDescription, "onboardingComplete")
else -> configure(message ?: "", text ?: "", type)
}
}
private fun configure(titleID: Int, descriptionID: Int, iconName: String) {
binding.titleView.text = context.getString(titleID)
binding.descriptionView.text = context.getString(descriptionID)
configure(context.getString(titleID), context.getString(descriptionID), iconName)
}
private fun configure(title: String, description: String, iconName: String) {
binding.titleView.text = title
binding.descriptionView.text = description
DataBindingUtils.loadImage(binding.iconView, "achievement-${iconName}2x")
if (iconName == "onboardingComplete") {
setTitle(R.string.onboardingComplete_achievement_title)
@ -54,11 +59,10 @@ class AchievementDialog(context: Context) : HabiticaAlertDialog(context) {
binding.achievementWrapper.visibility = View.GONE
binding.onboardingDoneIcon.visibility = View.VISIBLE
binding.titleView.typeface = Typeface.DEFAULT
val titleText = context.getString(titleID)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.titleView.setText(Html.fromHtml(titleText, Html.FROM_HTML_MODE_LEGACY), TextView.BufferType.SPANNABLE)
binding.titleView.setText(Html.fromHtml(title, Html.FROM_HTML_MODE_LEGACY), TextView.BufferType.SPANNABLE)
} else {
binding.titleView.setText(Html.fromHtml(titleText), TextView.BufferType.SPANNABLE)
binding.titleView.setText(Html.fromHtml(title), TextView.BufferType.SPANNABLE)
}
} else {
setTitle(R.string.achievement_title)

View file

@ -101,11 +101,11 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
var hatchPrice = 0
if (!hasEgg) {
hatchPrice = getItemPrice(pet, egg, hasUnlockedEgg)
hatchPrice += getItemPrice(pet, egg, hasUnlockedEgg)
}
if (!hasPotion) {
hatchPrice = getItemPrice(pet, potion, hasUnlockedPotion)
hatchPrice += getItemPrice(pet, potion, hasUnlockedPotion)
}
@ -128,7 +128,9 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
if (!hasPotion) {
observable = observable.flatMap { activity.inventoryRepository.purchaseItem("hatchingPotions", thisPotion.key, 1) }
}
observable.subscribe({
observable
.flatMap { activity.userRepository.retrieveUser(true, forced = true) }
.subscribe({
(getActivity() as? MainActivity)?.hatchPet(thisPotion, thisEgg)
}, RxErrorHandler.handleEmptyError())
}

View file

@ -51,6 +51,7 @@ class WorldStateSerialization: JsonDeserializer<WorldState> {
val event = json.asJsonObject?.getAsJsonObject("currentEvent")
if (event != null) {
state.currentEventKey = event.getAsString("event")
state.currentEventPromo = if (event.has("promo")) event.getAsString("promo") else null
state.currentEventStartDate = context?.deserialize(event.get("start"), Date::class.java)
state.currentEventEndDate = context?.deserialize(event.get("end"), Date::class.java)
}

View file

@ -10,7 +10,7 @@
{
"type": "SINGLE",
"filters": [],
"versionCode": 2659,
"versionCode": 2671,
"versionName": "3.1",
"outputFile": "Habitica-staff-release.apk"
}

View file

@ -1 +1 @@
Thanks for helping us testing!
This update is full of bug fixes and quality of life upgrades. You can now use the Fortify Potion! If your tasks are getting out of hand and youre overwhelmed with red, just get a Fortify Potion from the Market and it will reset all tasks to a neutral value. Youll now receive an in-app message when youve won a Challenge and won Challenges will be listed in your Achievements. Weve also improved the flow for hatching Pets, receiving Pet Achievements, starting Quests, and creating Challenges.