multiple fixes

This commit is contained in:
Phillip Thelen 2022-12-19 14:40:02 +01:00
parent c263d27e7c
commit bc685cdc82
64 changed files with 192 additions and 304 deletions

View file

@ -2,8 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="com.habitrpg.android.habitica" package="com.habitrpg.android.habitica"
android:versionCode="104"
android:versionName="0.0.32"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:installLocation="auto" > android:installLocation="auto" >

View file

@ -21,7 +21,6 @@
-keepattributes Signature -keepattributes Signature
-keepattributes *Annotation* -keepattributes *Annotation*
-keepattributes Exceptions -keepattributes Exceptions
-keep class sun.misc.Unsafe { *; }
#retrolambda #retrolambda
-dontwarn java.lang.invoke.* -dontwarn java.lang.invoke.*
@ -33,18 +32,10 @@
long consumerIndex; long consumerIndex;
} }
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
#OkHttp #OkHttp
-keep class okhttp3.** { *; } -keep class okhttp3.** { *; }
-keep,includedescriptorclasses class okio.Source -keep,includedescriptorclasses class okio.Source
-keep,includedescriptorclasses class okio.okio.Buffer
-keep interface okhttp3.** { *; } -keep interface okhttp3.** { *; }
-dontwarn okhttp3.** -dontwarn okhttp3.**
@ -82,17 +73,6 @@
-keep class com.crashlytics.** { *; } -keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.** -dontwarn com.crashlytics.**
#fresko
# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.common.internal.DoNotStrip *;
}
# Keep native methods # Keep native methods
-keepclassmembers class * { -keepclassmembers class * {
native <methods>; native <methods>;
@ -102,10 +82,6 @@
-keep class com.google.android.gms.ads.** { *; } -keep class com.google.android.gms.ads.** { *; }
#end amplitude #end amplitude
#playservices
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { -keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL; public static final *** NULL;
@ -138,9 +114,6 @@
#keep all enums #keep all enums
-keepclassmembers enum * { *; } -keepclassmembers enum * { *; }
-keep class Type {
public *;
}
-keepclassmembers class * extends java.lang.Enum { -keepclassmembers class * extends java.lang.Enum {
<fields>; <fields>;
public static **[] values(); public static **[] values();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 B

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

View file

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="@color/brand_200" />
</shape>
</item>
<item>
<bitmap
android:gravity="start|top"
android:src="@drawable/gold_coins_left" />
</item>
<item>
<bitmap
android:gravity="end|bottom"
android:src="@drawable/gold_coins_right" />
</item>
</layer-list>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="24dp" android:height="80dp" />
<solid android:color="?attr/colorWindowBackground" />
<corners android:topRightRadius="8dp" android:bottomRightRadius="8dp" />
</shape>

View file

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

View file

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

View file

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

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f9f9f9" />
<corners android:radius="3dp"/>
<stroke android:color="#1a000000" android:width="1dp"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="1dip" />
<solid android:color="@color/separator" />
</shape>

View file

@ -3,8 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
android:background="?colorContentBackground">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -3,8 +3,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
android:background="?attr/colorContentBackground">
<FrameLayout <FrameLayout
android:id="@+id/confetti_anchor" android:id="@+id/confetti_anchor"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -4,8 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
android:background="?attr/colorContentBackground">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -2,9 +2,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:tools="http://schemas.android.com/tools"
android:background="?attr/colorContentBackground">
<FrameLayout <FrameLayout
android:id="@+id/confetti_container" android:id="@+id/confetti_container"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -3,8 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="?attr/colorContentBackground">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -5,5 +5,4 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="8dp" android:padding="8dp"/>
android:background="?attr/colorContentBackground"/>

View file

@ -3,18 +3,19 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?colorPrimaryOffset"
android:orientation="vertical" android:orientation="vertical"
tools:context="com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment"> tools:context="com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment">
<LinearLayout <LinearLayout
android:id="@+id/menuHeaderView" android:id="@+id/menuHeaderView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="64dp" android:layout_height="wrap_content"
android:minHeight="64dp"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="1dp" android:paddingEnd="1dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:background="?colorPrimaryOffset"
android:baselineAligned="false"> android:baselineAligned="false">
<com.habitrpg.android.habitica.ui.views.RoundedCornerLayout <com.habitrpg.android.habitica.ui.views.RoundedCornerLayout
@ -154,7 +155,6 @@
tools:text="1" tools:text="1"
tools:visibility="visible" /> tools:visibility="visible" />
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
<com.habitrpg.android.habitica.ui.views.social.QuestMenuView <com.habitrpg.android.habitica.ui.views.social.QuestMenuView
android:id="@+id/questMenuView" android:id="@+id/questMenuView"

View file

@ -4,8 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/refreshLayout" android:id="@+id/refreshLayout">
android:background="?attr/colorContentBackground">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">

View file

@ -4,8 +4,7 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:parentTag="android.widget.RelativeLayout" tools:parentTag="android.widget.RelativeLayout">
android:background="?attr/colorWindowBackground">
<LinearLayout <LinearLayout
android:id="@+id/contentWrapper" android:id="@+id/contentWrapper"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -4,8 +4,7 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:parentTag="android.widget.RelativeLayout" tools:parentTag="android.widget.RelativeLayout">
android:background="?attr/colorWindowBackground">
<LinearLayout <LinearLayout
android:id="@+id/contentWrapper" android:id="@+id/contentWrapper"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -2,8 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="?attr/colorContentBackground">
<com.habitrpg.common.habitica.views.AvatarView <com.habitrpg.common.habitica.views.AvatarView
android:id="@+id/avatar_view" android:id="@+id/avatar_view"

View file

@ -3,8 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:background="@color/transparent">
<ImageView <ImageView
android:id="@+id/npc_image_view" android:id="@+id/npc_image_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -132,7 +132,7 @@
android:layout_gravity="center_vertical" /> android:layout_gravity="center_vertical" />
</LinearLayout> </LinearLayout>
<RelativeLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
@ -141,106 +141,71 @@
android:id="@+id/divider" android:id="@+id/divider"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_centerHorizontal="true"
android:visibility="invisible" /> android:visibility="invisible" />
<RelativeLayout <LinearLayout
android:id="@+id/months_subscribed_layout"
style="@style/subscriptionBox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="5dp" android:orientation="horizontal">
android:layout_marginBottom="6dp" <LinearLayout
android:layout_toStartOf="@id/divider"> android:id="@+id/months_subscribed_layout"
style="@style/subscriptionBox"
<View
android:id="@+id/months_divider"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_weight="1"
android:layout_centerHorizontal="true" /> android:layout_height="fill_parent"
android:orientation="vertical"
<ImageView android:layout_marginEnd="@dimen/spacing_medium"
android:id="@+id/calendar_icon" android:gravity="center">
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="8dp"
android:layout_toStartOf="@id/months_divider"
android:src="@drawable/calendar_ic" />
<TextView
style="@style/subscriptionBoxCompactText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/calendar_icon"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dp"
android:text="@string/months_subscribed"
android:gravity="center"
android:fontFamily="sans-serif-medium"/>
<TextView <TextView
android:id="@+id/monthsSubscribedTextView" android:id="@+id/monthsSubscribedTextView"
style="@style/subscriptionBoxCompactNumber" style="@style/subscriptionBoxCompactNumber"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="4dp" app:drawableStartCompat="@drawable/calendar_ic"
android:layout_marginTop="8dp" android:drawablePadding="@dimen/spacing_small"
android:layout_toEndOf="@id/calendar_icon"
android:gravity="center" android:gravity="center"
tools:text="2" /> tools:text="2" />
</RelativeLayout>
<RelativeLayout
style="@style/subscriptionBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginBottom="6dp"
android:layout_toEndOf="@id/divider">
<View
android:id="@+id/gem_divider"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/gem_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="10dp"
android:layout_toStartOf="@id/gem_divider"
android:src="@drawable/gem_ic" />
<TextView <TextView
style="@style/subscriptionBoxCompactText" style="@style/subscriptionBoxCompactText"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/gem_icon" android:text="@string/months_subscribed"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="@string/monthly_gem_cap"
android:gravity="center" android:gravity="center"
android:fontFamily="sans-serif-medium"/> android:fontFamily="sans-serif-medium"/>
</LinearLayout>
<LinearLayout
style="@style/subscriptionBox"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center">
<TextView <TextView
android:id="@+id/gemCapTextView" android:id="@+id/gemCapTextView"
style="@style/subscriptionBoxCompactNumber" style="@style/subscriptionBoxCompactNumber"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="4dp" app:drawableStartCompat="@drawable/gem_ic"
android:layout_marginTop="10dp" android:drawablePadding="@dimen/spacing_small"
android:layout_toEndOf="@id/gem_icon" android:gravity="center"
tools:text="50" /> tools:text="2" />
</RelativeLayout> <TextView
style="@style/subscriptionBoxCompactText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/months_subscribed"
android:gravity="center"
android:fontFamily="sans-serif-medium"/>
</LinearLayout>
</LinearLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/next_hourglass_container" android:id="@+id/next_hourglass_container"
style="@style/subscriptionBox" style="@style/subscriptionBox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_below="@id/months_subscribed_layout">
<ImageView <ImageView
android:layout_width="60dp" android:layout_width="60dp"
@ -276,7 +241,7 @@
android:textColor="@color/text_secondary"/> android:textColor="@color/text_secondary"/>
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </LinearLayout>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -740,8 +740,8 @@
<string name="server">Server</string> <string name="server">Server</string>
<string name="gift_confirmation_title">Your gift was sent!</string> <string name="gift_confirmation_title">Your gift was sent!</string>
<string name="gift_confirmation_text_sub_g1g1">You sent %s a %s-month Habitica subscription and the same subscription was applied to your account for our Gift One Get One promotion!</string> <string name="gift_confirmation_text_sub_g1g1">You sent %s a %s-month Habitica subscription and the same subscription was applied to your account for our Gift One Get One promotion!</string>
<string name="gift_confirmation_text_sub">You sent %s a %s-month Habitica subscription.</string> <string name="gift_confirmation_text_sub">You sent @%s a %s-month Habitica subscription.</string>
<string name="gift_confirmation_text_gems_new">You sent %s %s gems.</string> <string name="gift_confirmation_text_gems_new">You sent @%s %s gems.</string>
<string name="subscription_confirmation">You are now subscribed for 1 month</string> <string name="subscription_confirmation">You are now subscribed for 1 month</string>
<string name="subscription_confirmation_multiple">You are now subscribed for %s months</string> <string name="subscription_confirmation_multiple">You are now subscribed for %s months</string>
<string name="gem_purchase_confirmation">You gained %s gems.</string> <string name="gem_purchase_confirmation">You gained %s gems.</string>

View file

@ -1,15 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="ChallengeName"> <style name="ChallengeName">
<item name="android:fontFamily" tools:targetApi="jelly_bean">@string/font_family_condensed <item name="android:fontFamily" >@string/font_family_condensed</item>
</item>
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:textColor">@color/text_primary</item> <item name="android:textColor">@color/text_primary</item>
</style> </style>
<style name="ChallengeTaskDetails"> <style name="ChallengeTaskDetails">
<item name="android:fontFamily" tools:targetApi="jelly_bean">@string/font_family_regular <item name="android:fontFamily" >@string/font_family_regular</item>
</item>
<item name="android:textSize">12sp</item> <item name="android:textSize">12sp</item>
<item name="android:height">20dp</item> <item name="android:height">20dp</item>
<item name="android:textColor">#8a000000</item> <item name="android:textColor">#8a000000</item>

View file

@ -494,7 +494,7 @@
<style name="SubscriptionListTitle" parent="GemPurchaseListItem"> <style name="SubscriptionListTitle" parent="GemPurchaseListItem">
<item name="android:layout_gravity">left|center_vertical</item> <item name="android:layout_gravity">left|center_vertical</item>
<item name="android:fontFamily" tools:targetApi="jelly_bean">@string/font_family_medium</item> <item name="android:fontFamily" >@string/font_family_medium</item>
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="paddingEnd">32dp</item> <item name="paddingEnd">32dp</item>
</style> </style>
@ -571,7 +571,7 @@
<style name="subscriptionBoxText.Title"> <style name="subscriptionBoxText.Title">
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="android:fontFamily" tools:targetApi="jelly_bean"> <item name="android:fontFamily" >
@string/font_family_medium @string/font_family_medium
</item> </item>
<item name="android:textColor">@color/text_primary</item> <item name="android:textColor">@color/text_primary</item>
@ -580,7 +580,7 @@
<style name="subscriptionBoxText.Subtitle"> <style name="subscriptionBoxText.Subtitle">
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="android:fontFamily" tools:targetApi="jelly_bean"> <item name="android:fontFamily" >
@string/font_family_regular @string/font_family_regular
</item> </item>
<item name="android:textColor">@color/text_primary</item> <item name="android:textColor">@color/text_primary</item>
@ -588,7 +588,7 @@
<style name="SubscriptionListDescription" parent="GemPurchaseListItemDescription"> <style name="SubscriptionListDescription" parent="GemPurchaseListItemDescription">
<item name="android:layout_marginBottom">24dp</item> <item name="android:layout_marginBottom">24dp</item>
<item name="android:fontFamily" tools:targetApi="jelly_bean"> <item name="android:fontFamily" >
@string/font_family_condensed @string/font_family_condensed
</item> </item>
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>

View file

@ -26,4 +26,4 @@
"text": "test. todo", "text": "test. todo",
"userId": "MOCK", "userId": "MOCK",
"id": "66cb66bb-f04a-4219-bc60-664d1ec48f75" "id": "66cb66bb-f04a-4219-bc60-664d1ec48f75"
},] }]

View file

@ -192,11 +192,12 @@ class PurchaseHandler(
activity: Activity, activity: Activity,
skuDetails: SkuDetails, skuDetails: SkuDetails,
recipient: String? = null, recipient: String? = null,
recipientUsername: String? = null,
isSaleGemPurchase: Boolean = false isSaleGemPurchase: Boolean = false
) { ) {
this.isSaleGemPurchase = isSaleGemPurchase this.isSaleGemPurchase = isSaleGemPurchase
recipient?.let { recipient?.let {
addGift(skuDetails.sku, it) addGift(skuDetails.sku, it, recipientUsername ?: it)
} }
val flowParams = BillingFlowParams.newBuilder() val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails) .setSkuDetails(skuDetails)
@ -234,7 +235,7 @@ class PurchaseHandler(
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) { CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
consume(purchase) consume(purchase)
} }
displayConfirmationDialog(purchase, gift?.second) displayConfirmationDialog(purchase, gift?.third)
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
handleError(throwable, purchase) handleError(throwable, purchase)
} }
@ -250,7 +251,7 @@ class PurchaseHandler(
CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) { CoroutineScope(Dispatchers.IO).launch(ExceptionHandler.coroutine()) {
consume(purchase) consume(purchase)
} }
displayConfirmationDialog(purchase, gift?.second) displayConfirmationDialog(purchase, gift?.third)
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
handleError(throwable, purchase) handleError(throwable, purchase)
} }
@ -331,7 +332,7 @@ class PurchaseHandler(
val result = withContext(Dispatchers.IO) { val result = withContext(Dispatchers.IO) {
billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS)
} }
var fallback: Purchase? = null val fallback: Purchase? = null
if (result.billingResult.responseCode == BillingClient.BillingResponseCode.OK) { if (result.billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
return findMostRecentSubscription(result.purchasesList) return findMostRecentSubscription(result.purchasesList)
} }
@ -446,15 +447,15 @@ class PurchaseHandler(
companion object { companion object {
private const val PENDING_GIFTS_KEY = "PENDING_GIFTS_DATED" private const val PENDING_GIFTS_KEY = "PENDING_GIFTS_DATED"
private var pendingGifts: MutableMap<String, Pair<Date, String>> = HashMap() private var pendingGifts: MutableMap<String, Triple<Date, String, String>> = HashMap()
private var preferences: SharedPreferences? = null private var preferences: SharedPreferences? = null
fun addGift(sku: String, userID: String) { fun addGift(sku: String, userID: String, username: String) {
pendingGifts[sku] = Pair(Date(), userID) pendingGifts[sku] = Triple(Date(), userID, username)
savePendingGifts() savePendingGifts()
} }
private fun removeGift(sku: String?): Pair<Date, String>? { private fun removeGift(sku: String?): Triple<Date, String, String>? {
val gift = pendingGifts.remove(sku) val gift = pendingGifts.remove(sku)
savePendingGifts() savePendingGifts()
return gift return gift

View file

@ -72,7 +72,7 @@ class GiftSubscriptionActivity : PurchaseActivity() {
selectedSubscriptionSku?.let { sku -> purchaseSubscription(sku) } selectedSubscriptionSku?.let { sku -> purchaseSubscription(sku) }
} }
lifecycleScope.launch(ExceptionHandler.coroutine()) { lifecycleScope.launch(ExceptionHandler.coroutine()) {
val member = socialRepository.retrieveMember(giftedUsername ?: giftedUserID, true) ?: return@launch val member = socialRepository.retrieveMember(giftedUsername ?: giftedUserID) ?: return@launch
binding.avatarView.setAvatar(member) binding.avatarView.setAvatar(member)
binding.displayNameTextView.username = member.profile?.name binding.displayNameTextView.username = member.profile?.name
binding.displayNameTextView.tier = member.contributor?.level ?: 0 binding.displayNameTextView.tier = member.contributor?.level ?: 0
@ -139,7 +139,7 @@ class GiftSubscriptionActivity : PurchaseActivity() {
if (id.isEmpty()) { if (id.isEmpty()) {
return return
} }
PurchaseHandler.addGift(sku.sku, id) PurchaseHandler.addGift(sku.sku, id, giftedUsername ?: id)
purchaseHandler.purchase(this, sku) purchaseHandler.purchase(this, sku)
} }
} }

View file

@ -99,6 +99,7 @@ class ReportMessageActivity : BaseActivity() {
lifecycleScope.launch(ExceptionHandler.coroutine { lifecycleScope.launch(ExceptionHandler.coroutine {
isReporting = false isReporting = false
}) { }) {
socialRepository.flagMessage(messageID ?: "", binding.additionalInfoEdittext.text.toString(), groupID)
finish() finish()
} }
} }

View file

@ -21,6 +21,8 @@ import com.habitrpg.android.habitica.ui.viewHolders.ShopItemViewHolder
class ShopRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() { class ShopRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
var onNeedsRefresh: (() -> Unit)? = null
private val items: MutableList<Any> = ArrayList() private val items: MutableList<Any> = ArrayList()
private var shopIdentifier: String? = null private var shopIdentifier: String? = null
private var ownedItems: Map<String, OwnedItem> = HashMap() private var ownedItems: Map<String, OwnedItem> = HashMap()
@ -94,6 +96,7 @@ class ShopRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<an
val viewHolder = ShopItemViewHolder(view) val viewHolder = ShopItemViewHolder(view)
viewHolder.shopIdentifier = shopIdentifier viewHolder.shopIdentifier = shopIdentifier
viewHolder viewHolder
viewHolder
} }
} }

View file

@ -604,9 +604,6 @@ class NavigationDrawerFragment : DialogFragment() {
) { ) {
fragmentContainerView = activity?.findViewById(fragmentId) fragmentContainerView = activity?.findViewById(fragmentId)
this.drawerLayout = drawerLayout this.drawerLayout = drawerLayout
// set a custom shadow that overlays the main content when the drawer opens
this.drawerLayout?.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START)
// set UP the drawer's list view with items and click listener // set UP the drawer's list view with items and click listener
lifecycleScope.launchCatching { lifecycleScope.launchCatching {

View file

@ -4,6 +4,11 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@ -19,12 +24,11 @@ import com.habitrpg.android.habitica.models.shops.Shop
import com.habitrpg.android.habitica.models.shops.ShopCategory import com.habitrpg.android.habitica.models.shops.ShopCategory
import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.shops.ShopItem
import com.habitrpg.android.habitica.models.social.Group import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.CurrencyViews import com.habitrpg.android.habitica.ui.views.CurrencyText
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.common.habitica.helpers.RecyclerViewState import com.habitrpg.common.habitica.helpers.RecyclerViewState
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
@ -34,14 +38,16 @@ import javax.inject.Inject
open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>() { open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>() {
internal val currencyView: CurrencyViews by lazy { internal val currencyView: ComposeView by lazy {
val view = CurrencyViews(context) return@lazy ComposeView(requireContext())
view
} }
var adapter: ShopRecyclerAdapter? = null var adapter: ShopRecyclerAdapter? = null
var shopIdentifier: String? = null var shopIdentifier: String? = null
var shop: Shop? = null var shop: Shop? = null
internal val hourglasses = mutableStateOf<Double?>(null)
private val gems = mutableStateOf<Double?>(null)
private val gold = mutableStateOf<Double?>(null)
@Inject @Inject
lateinit var inventoryRepository: InventoryRepository lateinit var inventoryRepository: InventoryRepository
@Inject @Inject
@ -79,6 +85,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initializeCurrencyViews()
toolbarAccessoryContainer?.addView(currencyView) toolbarAccessoryContainer?.addView(currencyView)
binding?.recyclerView?.setBackgroundResource(R.color.content_background) binding?.recyclerView?.setBackgroundResource(R.color.content_background)
binding?.recyclerView?.onRefresh = { binding?.recyclerView?.onRefresh = {
@ -90,6 +97,12 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
adapter = binding?.recyclerView?.adapter as? ShopRecyclerAdapter adapter = binding?.recyclerView?.adapter as? ShopRecyclerAdapter
if (adapter == null) { if (adapter == null) {
adapter = ShopRecyclerAdapter() adapter = ShopRecyclerAdapter()
adapter?.onNeedsRefresh = {
loadShopInventory()
if (Shop.MARKET == shopIdentifier) {
loadMarketGear()
}
}
adapter?.context = context adapter?.context = context
binding?.recyclerView?.adapter = adapter binding?.recyclerView?.adapter = adapter
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator() binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
@ -102,7 +115,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
layoutManager = GridLayoutManager(context, 2) layoutManager = GridLayoutManager(context, 2)
layoutManager?.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { layoutManager?.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int { override fun getSpanSize(position: Int): Int {
return if (adapter?.getItemViewType(position) ?: 0 < 3) { return if ((adapter?.getItemViewType(position) ?: 0) < 3) {
layoutManager?.spanCount ?: 1 layoutManager?.spanCount ?: 1
} else { } else {
1 1
@ -134,7 +147,9 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
userViewModel.user.observe(viewLifecycleOwner) { userViewModel.user.observe(viewLifecycleOwner) {
adapter?.user = it adapter?.user = it
updateCurrencyView(it) hourglasses.value = it?.hourglassCount?.toDouble() ?: 0.0
gems.value = it?.gemCount?.toDouble() ?: 0.0
gold.value = it?.stats?.gp ?: 0.0
} }
lifecycleScope.launch(ExceptionHandler.coroutine()) { lifecycleScope.launch(ExceptionHandler.coroutine()) {
@ -149,11 +164,18 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
view.post { setGridSpanCount(view.width) } view.post { setGridSpanCount(view.width) }
currencyView.hourglassVisibility = View.GONE
context?.let { analyticsManager.logEvent("open_shop", bundleOf(Pair("shopIdentifier", shopIdentifier))) } context?.let { analyticsManager.logEvent("open_shop", bundleOf(Pair("shopIdentifier", shopIdentifier))) }
} }
open fun initializeCurrencyViews() {
currencyView.setContent {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
gems.value?.let { CurrencyText(currency = "gems", value = it) }
gold.value?.let { CurrencyText(currency = "gold", value = it) }
}
}
}
private fun showClassChangeDialog(classIdentifier: String) { private fun showClassChangeDialog(classIdentifier: String) {
context?.let { context -> context?.let { context ->
val alert = HabiticaAlertDialog(context) val alert = HabiticaAlertDialog(context)
@ -295,10 +317,4 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
companion object { companion object {
private const val SHOP_IDENTIFIER_KEY = "SHOP_IDENTIFIER_KEY" private const val SHOP_IDENTIFIER_KEY = "SHOP_IDENTIFIER_KEY"
} }
private fun updateCurrencyView(user: User?) {
currencyView.gold = user?.stats?.gp ?: 0.0
currencyView.gems = user?.gemCount?.toDouble() ?: 0.0
currencyView.hourglasses = user?.hourglassCount?.toDouble() ?: 0.0
}
} }

View file

@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.habitrpg.android.habitica.models.shops.Shop import com.habitrpg.android.habitica.models.shops.Shop
import com.habitrpg.android.habitica.ui.views.CurrencyText
class TimeTravelersShopFragment : ShopFragment() { class TimeTravelersShopFragment : ShopFragment() {
override fun onCreateView( override fun onCreateView(
@ -18,9 +19,12 @@ class TimeTravelersShopFragment : ShopFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initializeCurrencyViews()
}
currencyView.goldVisibility = View.GONE override fun initializeCurrencyViews() {
currencyView.gemVisibility = View.GONE currencyView.setContent {
currencyView.hourglassVisibility = View.VISIBLE hourglasses.value?.let { CurrencyText(currency = "hourglasses", value = it) }
}
} }
} }

View file

@ -126,7 +126,7 @@ class GemsPurchaseFragment : BaseFragment<FragmentGemPurchaseBinding>() {
private fun purchaseGems(view: GemPurchaseOptionsView?) { private fun purchaseGems(view: GemPurchaseOptionsView?) {
val identifier = view?.sku ?: return val identifier = view?.sku ?: return
activity?.let { purchaseHandler.purchase(it, identifier, null, isGemSaleHappening) } activity?.let { purchaseHandler.purchase(it, identifier, null, null, isGemSaleHappening) }
} }
private fun showGiftGemsDialog() { private fun showGiftGemsDialog() {

View file

@ -88,7 +88,7 @@ class GiftPurchaseGemsFragment : BaseFragment<FragmentGiftGemPurchaseBinding>()
private fun purchaseGems(sku: SkuDetails) { private fun purchaseGems(sku: SkuDetails) {
giftedMember?.id?.let { giftedMember?.id?.let {
activity?.let { it1 -> purchaseHandler?.purchase(it1, sku, it) } activity?.let { it1 -> purchaseHandler?.purchase(it1, sku, it, giftedMember?.username) }
} }
} }
} }

View file

@ -18,6 +18,7 @@ class ShopItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), Vi
private val binding = RowShopitemBinding.bind(itemView) private val binding = RowShopitemBinding.bind(itemView)
var shopIdentifier: String? = null var shopIdentifier: String? = null
private var item: ShopItem? = null private var item: ShopItem? = null
var onNeedsRefresh: (() -> Unit)? = null
private var context: Context = itemView.context private var context: Context = itemView.context
@ -101,6 +102,9 @@ class ShopItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), Vi
dialog.purchaseCardAction = { dialog.purchaseCardAction = {
purchaseCardAction?.invoke(it) purchaseCardAction?.invoke(it)
} }
dialog.onGearPurchased = {
onNeedsRefresh?.invoke()
}
dialog.show() dialog.show()
} }
} }

View file

@ -33,7 +33,8 @@ import com.habitrpg.common.habitica.api.HostConfig
import com.habitrpg.common.habitica.helpers.KeyHelper import com.habitrpg.common.habitica.helpers.KeyHelper
import com.habitrpg.common.habitica.models.auth.UserAuthResponse import com.habitrpg.common.habitica.models.auth.UserAuthResponse
import com.willowtreeapps.signinwithapplebutton.SignInWithAppleConfiguration import com.willowtreeapps.signinwithapplebutton.SignInWithAppleConfiguration
import kotlinx.coroutines.MainScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import javax.inject.Inject import javax.inject.Inject
class AuthenticationViewModel() { class AuthenticationViewModel() {
@ -111,7 +112,7 @@ class AuthenticationViewModel() {
val scopesString = Scopes.PROFILE + " " + Scopes.EMAIL val scopesString = Scopes.PROFILE + " " + Scopes.EMAIL
val scopes = "oauth2:$scopesString" val scopes = "oauth2:$scopesString"
var newUser = false var newUser = false
MainScope().launchCatching({ throwable -> CoroutineScope(Dispatchers.IO).launchCatching({ throwable ->
if (recoverFromPlayServicesErrorResult == null) return@launchCatching if (recoverFromPlayServicesErrorResult == null) return@launchCatching
throwable.cause?.let { throwable.cause?.let {
if (GoogleAuthException::class.java.isAssignableFrom(it.javaClass)) { if (GoogleAuthException::class.java.isAssignableFrom(it.javaClass)) {

View file

@ -106,6 +106,7 @@ fun AppHeaderView(
value = user?.stats?.exp ?: 0.0, value = user?.stats?.exp ?: 0.0,
maxValue = user?.stats?.toNextLevel?.toDouble() ?: 0.0, maxValue = user?.stats?.toNextLevel?.toDouble() ?: 0.0,
displayCompact = teamPlan != null, displayCompact = teamPlan != null,
abbreviateValue = false,
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
if (user?.hasClass == true) { if (user?.hasClass == true) {

View file

@ -1,8 +1,10 @@
package com.habitrpg.android.habitica.ui.views package com.habitrpg.android.habitica.ui.views
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.ProgressIndicatorDefaults
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -23,6 +25,10 @@ fun CurrencyText(
decimals: Int = 2, decimals: Int = 2,
minForAbbrevation: Int = 0 minForAbbrevation: Int = 0
) { ) {
val animatedValue = animateFloatAsState(
targetValue = value.toFloat(),
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
).value
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) { Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
when (currency) { when (currency) {
"gold" -> HabiticaIconsHelper.imageOfGold() "gold" -> HabiticaIconsHelper.imageOfGold()
@ -31,7 +37,7 @@ fun CurrencyText(
else -> null else -> null
}?.asImageBitmap()?.let { Image(it, null, Modifier.padding(end = 5.dp)) } }?.asImageBitmap()?.let { Image(it, null, Modifier.padding(end = 5.dp)) }
Text( Text(
NumberAbbreviator.abbreviate(null, value, decimals, minForAbbrevation), NumberAbbreviator.abbreviate(null, animatedValue, decimals, minForAbbrevation),
color = when (currency) { color = when (currency) {
"gold" -> colorResource(R.color.text_gold) "gold" -> colorResource(R.color.text_gold)
"gems" -> colorResource(R.color.text_green) "gems" -> colorResource(R.color.text_green)

View file

@ -35,6 +35,7 @@ import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
import com.habitrpg.common.habitica.helpers.NumberAbbreviator import com.habitrpg.common.habitica.helpers.NumberAbbreviator
import java.text.NumberFormat
@Composable @Composable
fun LabeledBar( fun LabeledBar(
@ -47,14 +48,19 @@ fun LabeledBar(
maxValue: Double, maxValue: Double,
displayCompact: Boolean = false, displayCompact: Boolean = false,
barHeight: Dp = 8.dp, barHeight: Dp = 8.dp,
disabled: Boolean = false disabled: Boolean = false,
abbreviateValue: Boolean = true,
abbreviateMax: Boolean = true
) { ) {
val cleanedMaxVlaue = java.lang.Double.max(1.0, maxValue) val cleanedMaxValue = java.lang.Double.max(1.0, maxValue)
val animatedValue = animateFloatAsState( val animatedValue = animateFloatAsState(
targetValue = value.toFloat(), targetValue = value.toFloat(),
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec, animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
).value ).value
val formatter = NumberFormat.getNumberInstance()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = modifier.alpha(if (disabled) 0.5f else 1.0f) modifier = modifier.alpha(if (disabled) 0.5f else 1.0f)
@ -70,7 +76,7 @@ fun LabeledBar(
} }
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
LinearProgressIndicator( LinearProgressIndicator(
progress = (animatedValue / cleanedMaxVlaue).toFloat(), progress = (animatedValue / cleanedMaxValue).toFloat(),
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.clip(CircleShape) .clip(CircleShape)
@ -84,8 +90,18 @@ fun LabeledBar(
modifier = Modifier.padding(top = 2.dp) modifier = Modifier.padding(top = 2.dp)
) { ) {
if (!disabled) { if (!disabled) {
val currentValueText = if (abbreviateValue) NumberAbbreviator.abbreviate(
LocalContext.current,
animatedValue,
0
) else formatter.format(animatedValue)
val maxValueText = if (abbreviateMax) NumberAbbreviator.abbreviate(
LocalContext.current,
cleanedMaxValue,
0
) else formatter.format(cleanedMaxValue)
Text( Text(
"${NumberAbbreviator.abbreviate(LocalContext.current, animatedValue)} / ${NumberAbbreviator.abbreviate(LocalContext.current, cleanedMaxVlaue)}", "$currentValueText / $maxValueText",
fontSize = 12.sp, fontSize = 12.sp,
color = colorResource(R.color.text_ternary) color = colorResource(R.color.text_ternary)
) )
@ -118,7 +134,18 @@ private fun Preview() {
color = colorResource(R.color.xpColor), color = colorResource(R.color.xpColor),
value = 100123.0, value = 100123.0,
maxValue = 50000000000000.0, maxValue = 50000000000000.0,
displayCompact = false displayCompact = false,
abbreviateValue = false
)
LabeledBar(
icon = HabiticaIconsHelper.imageOfExperience(),
label = stringResource(id = R.string.XP_default),
color = colorResource(R.color.xpColor),
value = 100123.0,
maxValue = 50000000000000.0,
displayCompact = false,
abbreviateValue = false,
abbreviateMax = false
) )
LabeledBar( LabeledBar(
icon = HabiticaIconsHelper.imageOfMagic(), icon = HabiticaIconsHelper.imageOfMagic(),

View file

@ -96,13 +96,11 @@ class SubscriptionDetailsView : LinearLayout {
binding.monthsSubscribedTextView.text = plan.consecutive?.count.toString() binding.monthsSubscribedTextView.text = plan.consecutive?.count.toString()
binding.gemCapTextView.text = plan.totalNumberOfGems.toString() binding.gemCapTextView.text = plan.totalNumberOfGems.toString()
if (plan.isActive && plan.dateTerminated == null) { if (plan.isActive && plan.dateTerminated == null) {
plan.monthsUntilNextHourglass?.let { nextHourglass ->
val now = LocalDate.now() val now = LocalDate.now()
val nextHourglassDate = LocalDate.now().plusMonths(nextHourglass.toLong()) val nextHourglassDate = LocalDate.now().plusMonths(plan.monthsUntilNextHourglass.toLong())
val format = if (now.year != nextHourglassDate.year) { val format = if (now.year != nextHourglassDate.year) {
"MM YYYY" "MM YYYY"
} else { } else {
@ -111,7 +109,6 @@ class SubscriptionDetailsView : LinearLayout {
val nextHourglassMonth = nextHourglassDate.format(DateTimeFormatter.ofPattern(format)) val nextHourglassMonth = nextHourglassDate.format(DateTimeFormatter.ofPattern(format))
nextHourglassMonth?.let { binding.nextHourglassTextview.text = it } nextHourglassMonth?.let { binding.nextHourglassTextview.text = it }
binding.nextHourglassContainer.isVisible = true binding.nextHourglassContainer.isVisible = true
}
} else { } else {
binding.nextHourglassContainer.isVisible = false binding.nextHourglassContainer.isVisible = false
} }

View file

@ -12,6 +12,7 @@ object NumberAbbreviator {
} }
fun abbreviate(context: Context?, number: Double, numberOfDecimals: Int = 2, minForAbbrevation: Int = 0): String { fun abbreviate(context: Context?, number: Double, numberOfDecimals: Int = 2, minForAbbrevation: Int = 0): String {
val decimalCount = if (number > -1 && number < 1 && numberOfDecimals == 0) 1 else numberOfDecimals
var usedNumber = number var usedNumber = number
var counter = 0 var counter = 0
while (usedNumber >= 1000 && number >= minForAbbrevation) { while (usedNumber >= 1000 && number >= minForAbbrevation) {
@ -19,7 +20,7 @@ object NumberAbbreviator {
usedNumber /= 1000 usedNumber /= 1000
} }
var pattern = "###" var pattern = "###"
if (numberOfDecimals > 0) { if (decimalCount > 0) {
pattern = ("$pattern.").padEnd(4 + numberOfDecimals, '#') pattern = ("$pattern.").padEnd(4 + numberOfDecimals, '#')
} }
val formatter = DecimalFormat(pattern + abbreviationForCounter(context, counter).replace(".", "")) val formatter = DecimalFormat(pattern + abbreviationForCounter(context, counter).replace(".", ""))

View file

@ -1,4 +1,2 @@
fabric_key=
facebook_app_id=
amplitude_app_id= amplitude_app_id=
application_ad_id= application_ad_id=

View file

@ -22,7 +22,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation("io.realm.kotlin:library-base:1.0.2") implementation("io.realm.kotlin:library-base:1.5.0")
} }
} }
val commonTest by getting { val commonTest by getting {

View file

@ -1,2 +1,2 @@
NAME=4.1 NAME=4.1
CODE=4831 CODE=4841

View file