mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-13 17:51:57 +00:00
Begin implementing new challenge design and layout
This commit is contained in:
parent
5040574bf0
commit
5626b76956
54 changed files with 4538 additions and 1671 deletions
10
Habitica/res/drawable/border_1f000000_white.xml
Normal file
10
Habitica/res/drawable/border_1f000000_white.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
<stroke
|
||||
android:width="0.5dip"
|
||||
android:color="#2f000000"/>
|
||||
|
||||
</shape>
|
||||
6
Habitica/res/drawable/circle_white.xml
Normal file
6
Habitica/res/drawable/circle_white.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
</shape>
|
||||
6
Habitica/res/drawable/pill_bg_white.xml
Normal file
6
Habitica/res/drawable/pill_bg_white.xml
Normal 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/white"/>
|
||||
<corners android:radius="20dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,30 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_1f000000"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_1f000000_white"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="60dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/lock_icon_background"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="@dimen/spacing_large"
|
||||
android:layout_marginTop="0.5dp"
|
||||
android:layout_marginBottom="0.5dp">
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/daily_checkbox" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
android:id="@+id/lock_icon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
|||
|
|
@ -4,45 +4,26 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/border_1f000000"
|
||||
android:background="@drawable/border_1f000000_white"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="60dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/lock_icon_background_plus"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/gray_700"
|
||||
android:layout_marginRight="@dimen/spacing_large"
|
||||
android:layout_marginTop="0.5dp"
|
||||
android:layout_marginBottom="0.5dp">
|
||||
<ImageView
|
||||
android:id="@+id/plus_img_tinted"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/plus"
|
||||
android:tint="#4d000000"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/plus_img"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/plus"
|
||||
android:tint="#1f000000"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
android:id="@+id/lock_icon_plus"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -63,40 +44,20 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/lock_icon_background_minus"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/gray_700"
|
||||
android:layout_marginLeft="@dimen/spacing_large"
|
||||
android:layout_marginTop="0.5dp"
|
||||
android:layout_marginBottom="0.5dp">
|
||||
<ImageView
|
||||
android:id="@+id/minus_img_tinted"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/minus"
|
||||
android:tint="#4d000000"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/minus_img"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/minus"
|
||||
android:tint="#1f000000"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
android:id="@+id/lock_icon_minus"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/border_1f000000"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/border_1f000000_white"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="60dp">
|
||||
<ImageView
|
||||
android:id="@+id/gold_icon"
|
||||
android:layout_width="16dp"
|
||||
|
|
|
|||
|
|
@ -4,20 +4,35 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/task_group_name"
|
||||
style="@style/Body1"
|
||||
android:layout_marginTop="13dp"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="2 Habits" />
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/spacing_large"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="@dimen/spacing_large"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/task_group_name"
|
||||
style="@style/Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Habits"
|
||||
android:textSize="15sp"/>
|
||||
<TextView
|
||||
android:id="@+id/task_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/spacing_medium"
|
||||
style="@style/Pill.White"
|
||||
android:textColor="@color/gray_400"
|
||||
tools:text="2"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tasks_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="11dp"
|
||||
android:background="@drawable/border_1f000000"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_1f000000"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_1f000000_white"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="60dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/lock_icon_background"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="@dimen/spacing_large"
|
||||
android:layout_marginTop="0.5dp"
|
||||
android:layout_marginBottom="0.5dp">
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginBottom="18dp"
|
||||
android:layout_marginEnd="15.5dp"
|
||||
android:layout_marginLeft="14.5dp"
|
||||
android:layout_marginRight="15.5dp"
|
||||
android:layout_marginStart="14.5dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:src="@drawable/todo_checkbox" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
android:id="@+id/lock_icon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
|||
210
Habitica/res/layout/fragment_challenge_detail.xml
Normal file
210
Habitica/res/layout/fragment_challenge_detail.xml
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:maxHeightMultiplier="0.7">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:scrollbarAlwaysDrawVerticalTrack="true"
|
||||
android:scrollbars="vertical"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:paddingBottom="?attr/actionBarSize">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
<net.pherth.android.emoji_library.EmojiTextView
|
||||
android:id="@+id/challenge_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
style="@style/Title1"
|
||||
android:textSize="18sp"
|
||||
tools:text="Challenge name"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:layout_marginBottom="@dimen/spacing_large">
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5"
|
||||
android:background="@drawable/layout_rounded_bg"
|
||||
android:padding="@dimen/spacing_medium"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginRight="@dimen/spacing_medium">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
<ImageView
|
||||
android:id="@+id/participant_count_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp" />
|
||||
<TextView
|
||||
android:id="@+id/participant_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="17sp"
|
||||
android:textColor="@color/gray_100"
|
||||
tools:text="5"
|
||||
android:layout_marginLeft="@dimen/spacing_small"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/participants"
|
||||
android:gravity="center"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/gray_200"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5"
|
||||
android:background="@drawable/layout_rounded_bg"
|
||||
android:padding="@dimen/spacing_medium"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginLeft="@dimen/spacing_medium">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
<ImageView
|
||||
android:id="@+id/gem_amount_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp" />
|
||||
<TextView
|
||||
android:id="@+id/gem_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="17sp"
|
||||
android:textColor="@color/gray_100"
|
||||
tools:text="5"
|
||||
android:layout_marginLeft="@dimen/spacing_small"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/challenge_prize"
|
||||
android:gravity="center"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/gray_200"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<FrameLayout
|
||||
android:id="@+id/join_button_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/spacing_large"
|
||||
android:paddingRight="@dimen/spacing_large"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingBottom="@dimen/spacing_medium"
|
||||
android:background="@color/white">
|
||||
<Button
|
||||
android:id="@+id/join_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/join"
|
||||
style="@style/HabiticaButton.Green"/>
|
||||
</FrameLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/spacing_large"
|
||||
android:paddingRight="@dimen/spacing_large"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingBottom="@dimen/spacing_medium"
|
||||
android:background="@color/white"
|
||||
android:orientation="horizontal">
|
||||
<com.habitrpg.android.habitica.ui.RoundedFrameLayout
|
||||
android:layout_width="@dimen/avatar_chat_size"
|
||||
android:layout_height="@dimen/avatar_chat_size"
|
||||
android:clipChildren="true"
|
||||
android:layout_marginRight="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:background="@drawable/rounded_avatar_bg">
|
||||
<com.habitrpg.android.habitica.ui.AvatarView
|
||||
android:id="@+id/creator_avatarview"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="center"
|
||||
app:showMount="false"
|
||||
app:showPet="false" />
|
||||
</com.habitrpg.android.habitica.ui.RoundedFrameLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1">
|
||||
<com.habitrpg.android.habitica.ui.views.social.UsernameLabel
|
||||
android:id="@+id/creator_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/created_challenge"
|
||||
android:textColor="@color/gray_200"
|
||||
android:textSize="12sp"/>
|
||||
</LinearLayout>
|
||||
<ImageButton
|
||||
android:id="@+id/creator_message_button"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/Base.Widget.AppCompat.Button.Borderless"/>
|
||||
</LinearLayout>
|
||||
<com.habitrpg.android.habitica.ui.views.CollapsibleSectionView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:title="@string/challenge_categories"
|
||||
android:background="@color/white">
|
||||
<net.pherth.android.emoji_library.EmojiTextView
|
||||
android:id="@+id/challenge_description"
|
||||
style="@style/Body2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="11dp"
|
||||
android:lineSpacingExtra="4sp"
|
||||
tools:text="There’s always more to learn! Maybe it’s a specialized topic you’re interested in, or maybe it’s the experiences of a notable contributor. Read about it and you may win 15 gems!" />
|
||||
</com.habitrpg.android.habitica.ui.views.CollapsibleSectionView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/task_group_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="13dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
<FrameLayout
|
||||
android:id="@+id/leave_button_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/spacing_large"
|
||||
android:paddingRight="@dimen/spacing_large"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingBottom="@dimen/spacing_large">
|
||||
<Button
|
||||
android:id="@+id/leave_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/leave"
|
||||
style="@style/HabiticaButton.Red"/>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
|
@ -782,4 +782,7 @@
|
|||
<string name="report">Report</string>
|
||||
<string name="like">Like</string>
|
||||
<string name="reply">Reply</string>
|
||||
<string name="challenge_prize">Challenge Prize</string>
|
||||
<string name="challenge_categories">Challenge Categories</string>
|
||||
<string name="created_challenge">Created Challenge</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -224,6 +224,10 @@
|
|||
<item name="android:paddingBottom">@dimen/pill_vertical_padding</item>
|
||||
</style>
|
||||
|
||||
<style name="Pill.White">
|
||||
<item name="android:background">@drawable/pill_bg_white</item>
|
||||
</style>
|
||||
|
||||
<style name="Pill.Selected">
|
||||
<item name="android:textColor">@color/white</item>
|
||||
<item name="android:background">@drawable/pill_bg_purple</item>
|
||||
|
|
|
|||
BIN
Habitica/src/main/assets/HelveticaNeue.ttc
Normal file
BIN
Habitica/src/main/assets/HelveticaNeue.ttc
Normal file
Binary file not shown.
|
|
@ -16,7 +16,6 @@ import com.habitrpg.android.habitica.receivers.NotificationPublisher;
|
|||
import com.habitrpg.android.habitica.receivers.TaskAlarmBootReceiver;
|
||||
import com.habitrpg.android.habitica.receivers.TaskReceiver;
|
||||
import com.habitrpg.android.habitica.ui.activities.AboutActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.CreateChallengeActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.FixCharacterValuesActivity;
|
||||
|
|
@ -79,9 +78,8 @@ import com.habitrpg.android.habitica.ui.fragments.social.PublicGuildsFragment;
|
|||
import com.habitrpg.android.habitica.ui.fragments.social.QuestDetailFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.TavernDetailFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.TavernFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailDialogHolder;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeListFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengesOverviewFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyDetailFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyFragment;
|
||||
|
|
@ -230,8 +228,6 @@ public interface AppComponent {
|
|||
|
||||
void inject(ChallengeListFragment challengeListFragment);
|
||||
|
||||
void inject(ChallengeDetailActivity challengeDetailActivity);
|
||||
|
||||
void inject(ApiClient apiClient);
|
||||
|
||||
void inject(TaskListWidgetProvider taskListWidgetProvider);
|
||||
|
|
@ -250,8 +246,6 @@ public interface AppComponent {
|
|||
|
||||
void inject(ChallengeTasksRecyclerViewAdapter challengeTasksRecyclerViewAdapter);
|
||||
|
||||
void inject(ChallengeTasksRecyclerViewFragment challengeTasksRecyclerViewFragment);
|
||||
|
||||
void inject(TaskListFactory taskListFactory);
|
||||
|
||||
void inject(GemPurchaseActivity gemPurchaseActivity);
|
||||
|
|
@ -272,8 +266,6 @@ public interface AppComponent {
|
|||
|
||||
void inject(CreateChallengeActivity createChallengeActivity);
|
||||
|
||||
void inject(ChallengeDetailDialogHolder challengeDetailDialogHolder);
|
||||
|
||||
void inject(TavernDetailFragment tavernDetailFragment);
|
||||
|
||||
void inject(PartyDetailFragment partyDetailFragment);
|
||||
|
|
@ -299,4 +291,6 @@ public interface AppComponent {
|
|||
void inject(WelcomeFragment welcomeFragment);
|
||||
|
||||
void inject(@NotNull NavigationDrawerFragment navigationDrawerFragment);
|
||||
|
||||
void inject(@NotNull ChallengeDetailFragment challengeDetailFragment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
package com.habitrpg.android.habitica.data;
|
||||
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Flowable;
|
||||
import io.realm.RealmResults;
|
||||
|
||||
public interface ChallengeRepository extends BaseRepository {
|
||||
Flowable<Challenge> getChallenge(String challengeId);
|
||||
Flowable<TaskList> getChallengeTasks(String challengeId);
|
||||
|
||||
Flowable<Challenge> createChallenge(Challenge challenge, List<Task> taskList);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param challenge the challenge that will be updated
|
||||
* @param fullTaskList lists all tasks of the current challenge, to create the taskOrders
|
||||
* @param addedTaskList only the tasks to be added online
|
||||
* @param updatedTaskList only the updated ones
|
||||
* @param removedTaskList tasks that has be to be removed
|
||||
* @return Observable with the updated challenge
|
||||
*/
|
||||
Flowable<Challenge> updateChallenge(Challenge challenge, List<Task> fullTaskList,
|
||||
List<Task> addedTaskList, List<Task> updatedTaskList, List<String> removedTaskList);
|
||||
Flowable<Void> deleteChallenge(String challengeId);
|
||||
|
||||
Flowable<RealmResults<Challenge>> getChallenges();
|
||||
Flowable<RealmResults<Challenge>> getUserChallenges(String userId);
|
||||
|
||||
Flowable<List<Challenge>> retrieveChallenges(User user);
|
||||
|
||||
Flowable<Void> leaveChallenge(Challenge challenge, LeaveChallengeBody leaveChallengeBody);
|
||||
|
||||
Flowable<Challenge> joinChallenge(Challenge challenge);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.habitrpg.android.habitica.data
|
||||
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
||||
import io.reactivex.Flowable
|
||||
import io.realm.RealmResults
|
||||
|
||||
interface ChallengeRepository : BaseRepository {
|
||||
|
||||
fun retrieveChallenges(user: User): Flowable<List<Challenge>>
|
||||
fun getChallenges(): Flowable<RealmResults<Challenge>>
|
||||
fun getChallenge(challengeId: String): Flowable<Challenge>
|
||||
fun getChallengeTasks(challengeId: String): Flowable<RealmResults<Task>>
|
||||
|
||||
fun retrieveChallenge(challengeID: String): Flowable<Challenge>
|
||||
fun retrieveChallengeTasks(challengeID: String): Flowable<TaskList>
|
||||
fun createChallenge(challenge: Challenge, taskList: List<Task>): Flowable<Challenge>
|
||||
|
||||
/**
|
||||
*
|
||||
* @param challenge the challenge that will be updated
|
||||
* @param fullTaskList lists all tasks of the current challenge, to create the taskOrders
|
||||
* @param addedTaskList only the tasks to be added online
|
||||
* @param updatedTaskList only the updated ones
|
||||
* @param removedTaskList tasks that has be to be removed
|
||||
* @return Observable with the updated challenge
|
||||
*/
|
||||
fun updateChallenge(challenge: Challenge, fullTaskList: List<Task>,
|
||||
addedTaskList: List<Task>, updatedTaskList: List<Task>, removedTaskList: List<String>): Flowable<Challenge>
|
||||
|
||||
fun deleteChallenge(challengeId: String): Flowable<Void>
|
||||
fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>>
|
||||
|
||||
|
||||
fun leaveChallenge(challenge: Challenge, leaveChallengeBody: LeaveChallengeBody): Flowable<Void>
|
||||
|
||||
fun joinChallenge(challenge: Challenge): Flowable<Challenge>
|
||||
|
||||
fun getChallengepMembership(id: String): Flowable<ChallengeMembership>
|
||||
fun getChallengeMemberships(): Flowable<RealmResults<ChallengeMembership>>
|
||||
fun isChallengeMember(challengeID: String): Flowable<Boolean>
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import com.habitrpg.android.habitica.models.responses.PostChatMessageResult
|
|||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.Single
|
||||
|
|
@ -72,4 +73,7 @@ interface SocialRepository : BaseRepository {
|
|||
fun forceStartQuest(party: Group): Flowable<Quest>
|
||||
|
||||
fun getMemberAchievements(userId: String?): Flowable<AchievementResult>
|
||||
|
||||
fun getGroupMembership(id: String): Flowable<GroupMembership>
|
||||
fun getGroupMemberships(): Flowable<RealmResults<GroupMembership>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,25 +6,51 @@ import com.habitrpg.android.habitica.data.ChallengeRepository
|
|||
import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.android.habitica.models.tasks.TasksOrder
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
import io.realm.RealmResults
|
||||
import java.util.*
|
||||
|
||||
|
||||
class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClient: ApiClient) : BaseRepositoryImpl<ChallengeLocalRepository>(localRepository, apiClient), ChallengeRepository {
|
||||
class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClient: ApiClient, private val userId: String) : BaseRepositoryImpl<ChallengeLocalRepository>(localRepository, apiClient), ChallengeRepository {
|
||||
override fun isChallengeMember(challengeID: String): Flowable<Boolean> {
|
||||
return localRepository.isChallengeMember(userId, challengeID)
|
||||
}
|
||||
|
||||
override fun getChallengepMembership(id: String): Flowable<ChallengeMembership> {
|
||||
return localRepository.getChallengeMembership(userId, id)
|
||||
}
|
||||
|
||||
override fun getChallengeMemberships(): Flowable<RealmResults<ChallengeMembership>> {
|
||||
return localRepository.getChallengeMemberships(userId)
|
||||
}
|
||||
|
||||
override fun getChallenge(challengeId: String): Flowable<Challenge> {
|
||||
return apiClient.getChallenge(challengeId)
|
||||
return localRepository.getChallenge(challengeId)
|
||||
}
|
||||
|
||||
override fun getChallengeTasks(challengeId: String): Flowable<TaskList> {
|
||||
return apiClient.getChallengeTasks(challengeId)
|
||||
override fun getChallengeTasks(challengeId: String): Flowable<RealmResults<Task>> {
|
||||
return localRepository.getTasks(challengeId)
|
||||
}
|
||||
|
||||
override fun retrieveChallenge(challengeID: String): Flowable<Challenge> {
|
||||
return apiClient.getChallenge(challengeID).doOnNext {
|
||||
localRepository.save(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun retrieveChallengeTasks(challengeID: String): Flowable<TaskList> {
|
||||
return apiClient.getChallengeTasks(challengeID).doOnNext {
|
||||
val taskList = it.tasks.values.toList()
|
||||
taskList.forEach {
|
||||
it.userId = challengeID
|
||||
}
|
||||
localRepository.save(taskList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTaskOrders(taskList: List<Task>): TasksOrder {
|
||||
val stringListMap = U.groupBy(taskList) { t -> t.type }
|
||||
|
|
@ -46,7 +72,7 @@ class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClie
|
|||
}
|
||||
|
||||
private fun addChallengeTasks(challenge: Challenge, addedTaskList: List<Task>): Flowable<Challenge> {
|
||||
return apiClient.createChallengeTasks(challenge.id, addedTaskList).map { challenge }
|
||||
return apiClient.createChallengeTasks(challenge.id ?: "", addedTaskList).map { challenge }
|
||||
}
|
||||
|
||||
override fun createChallenge(challenge: Challenge, taskList: List<Task>): Flowable<Challenge> {
|
||||
|
|
@ -95,17 +121,13 @@ class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClie
|
|||
.doOnNext { localRepository.saveChallenges(it) }
|
||||
}
|
||||
|
||||
override fun leaveChallenge(challenge: Challenge?, leaveChallengeBody: LeaveChallengeBody): Flowable<Void> {
|
||||
return if (challenge == null) {
|
||||
Flowable.empty()
|
||||
} else apiClient.leaveChallenge(challenge.id, leaveChallengeBody)
|
||||
.doOnNext { localRepository.setParticipating(challenge, false) }
|
||||
override fun leaveChallenge(challenge: Challenge, leaveChallengeBody: LeaveChallengeBody): Flowable<Void> {
|
||||
return apiClient.leaveChallenge(challenge.id ?: "", leaveChallengeBody)
|
||||
.doOnNext { localRepository.setParticipating(userId, challenge.id ?: "", false) }
|
||||
}
|
||||
|
||||
override fun joinChallenge(challenge: Challenge?): Flowable<Challenge> {
|
||||
return if (challenge == null) {
|
||||
Flowable.empty()
|
||||
} else apiClient.joinChallenge(challenge.id)
|
||||
.doOnNext { localRepository.setParticipating(challenge, true) }
|
||||
override fun joinChallenge(challenge: Challenge): Flowable<Challenge> {
|
||||
return apiClient.joinChallenge(challenge.id ?: "")
|
||||
.doOnNext { localRepository.setParticipating(userId, challenge.id ?: "", false) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.models.responses.PostChatMessageResult
|
|||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.Single
|
||||
|
|
@ -22,6 +23,13 @@ import java.util.*
|
|||
|
||||
|
||||
class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: ApiClient, private val userId: String) : BaseRepositoryImpl<SocialLocalRepository>(localRepository, apiClient), SocialRepository {
|
||||
override fun getGroupMembership(id: String): Flowable<GroupMembership> {
|
||||
return localRepository.getGroupMembership(userId, id)
|
||||
}
|
||||
|
||||
override fun getGroupMemberships(): Flowable<RealmResults<GroupMembership>> {
|
||||
return localRepository.getGroupMemberships(userId)
|
||||
}
|
||||
|
||||
override fun retrieveGroupChat(groupId: String): Single<List<ChatMessage>> {
|
||||
return apiClient.listGroupChat(groupId)
|
||||
|
|
@ -83,14 +91,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
}
|
||||
|
||||
override fun retrieveGroup(id: String): Flowable<Group> {
|
||||
var observable = apiClient.getGroup(id)
|
||||
if ("party" != id && localRepository.doesGroupExist(id)) {
|
||||
observable = observable.withLatestFrom(localRepository.getGroup(id), BiFunction<Group, Group, Group> { newGroup, oldGroup ->
|
||||
newGroup.isMember = oldGroup.isMember
|
||||
newGroup
|
||||
})
|
||||
}
|
||||
return Flowable.zip(observable.doOnNext { localRepository.save(it) }, retrieveGroupChat(id)
|
||||
return Flowable.zip(apiClient.getGroup(id).doOnNext { localRepository.save(it) }, retrieveGroupChat(id)
|
||||
.map {
|
||||
it.forEach {
|
||||
it.groupId = id
|
||||
|
|
@ -98,7 +99,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
return@map it
|
||||
}
|
||||
.doOnSuccess { localRepository.save(it) }.toFlowable(),
|
||||
BiFunction<Group, List<ChatMessage>, Group> { group, chat ->
|
||||
BiFunction<Group, List<ChatMessage>, Group> { group, _ ->
|
||||
group
|
||||
}
|
||||
)
|
||||
|
|
@ -117,7 +118,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
}
|
||||
return apiClient.leaveGroup(id)
|
||||
.flatMapMaybe { localRepository.getGroup(id).firstElement() }
|
||||
.doOnNext { group -> localRepository.executeTransaction { group.isMember = false } }
|
||||
.doOnNext { localRepository.executeTransaction { localRepository.updateMembership(userId, id, false) } }
|
||||
}
|
||||
|
||||
override fun joinGroup(id: String?): Flowable<Group> {
|
||||
|
|
@ -126,7 +127,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
}
|
||||
return apiClient.joinGroup(id)
|
||||
.doOnNext { group ->
|
||||
group?.isMember = true
|
||||
localRepository.updateMembership(userId, id, true)
|
||||
localRepository.save(group)
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +149,10 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
return apiClient.listGroups(type)
|
||||
.doOnNext { groups ->
|
||||
if ("guilds" == type) {
|
||||
groups.forEach { guild -> guild.isMember = true }
|
||||
val memberships = groups.map {
|
||||
return@map GroupMembership(userId, it.id)
|
||||
}
|
||||
localRepository.save(memberships)
|
||||
}
|
||||
localRepository.save(groups)
|
||||
}
|
||||
|
|
@ -195,7 +199,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
}
|
||||
}
|
||||
|
||||
override fun getUserGroups(): Flowable<RealmResults<Group>> = localRepository.getUserGroups()
|
||||
override fun getUserGroups(): Flowable<RealmResults<Group>> = localRepository.getUserGroups(userId)
|
||||
|
||||
override fun acceptQuest(user: User?, partyId: String): Flowable<Void> {
|
||||
return apiClient.acceptQuest(partyId)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.habitrpg.android.habitica.data.local
|
|||
|
||||
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
import io.reactivex.Flowable
|
||||
|
|
@ -11,11 +13,15 @@ interface ChallengeLocalRepository : BaseLocalRepository {
|
|||
|
||||
val challenges: Flowable<RealmResults<Challenge>>
|
||||
fun getChallenge(id: String): Flowable<Challenge>
|
||||
fun getTasks(challenge: Challenge): Flowable<List<Task>>
|
||||
fun getTasks(challengeID: String): Flowable<RealmResults<Task>>
|
||||
|
||||
fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>>
|
||||
|
||||
fun setParticipating(challenge: Challenge, isParticipating: Boolean)
|
||||
fun setParticipating(userID: String, challengeID: String, isParticipating: Boolean)
|
||||
|
||||
fun saveChallenges(challenges: List<Challenge>)
|
||||
fun getChallengeMembership(userId: String, id: String): Flowable<ChallengeMembership>
|
||||
fun getChallengeMemberships(userId: String): Flowable<RealmResults<ChallengeMembership>>
|
||||
fun isChallengeMember(userID: String, challengeID: String): Flowable<Boolean>
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ package com.habitrpg.android.habitica.data.local
|
|||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
|
||||
interface SocialLocalRepository : BaseLocalRepository {
|
||||
fun getPublicGuilds(): Flowable<RealmResults<Group>>
|
||||
|
||||
fun getUserGroups(): Flowable<RealmResults<Group>>
|
||||
fun getUserGroups(userID: String): Flowable<RealmResults<Group>>
|
||||
fun getGroups(type: String): Flowable<RealmResults<Group>>
|
||||
|
||||
fun getGroup(id: String): Flowable<Group>
|
||||
|
|
@ -34,4 +36,7 @@ interface SocialLocalRepository : BaseLocalRepository {
|
|||
fun saveChatMessages(groupId: String?, chatMessages: List<ChatMessage>)
|
||||
|
||||
fun doesGroupExist(id: String): Boolean
|
||||
fun updateMembership(userId: String, id: String, isMember: Boolean)
|
||||
fun getGroupMembership(userId: String, id: String): Flowable<GroupMembership>
|
||||
fun getGroupMemberships(userId: String): Flowable<RealmResults<GroupMembership>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,38 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import io.reactivex.Flowable
|
||||
import io.realm.OrderedRealmCollectionSnapshot
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
import io.realm.Sort
|
||||
import java.util.*
|
||||
|
||||
class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ChallengeLocalRepository {
|
||||
|
||||
override fun isChallengeMember(userID: String, challengeID: String): Flowable<Boolean> = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userID)
|
||||
.equalTo("challengeID", challengeID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.map { it.count() > 0 }
|
||||
|
||||
override fun getChallengeMembership(userId: String, id: String): Flowable<ChallengeMembership> = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.equalTo("challengeID", id)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.map { it.first() }
|
||||
|
||||
override fun getChallengeMemberships(userId: String): Flowable<RealmResults<ChallengeMembership>> = realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
|
||||
override fun getChallenge(id: String): Flowable<Challenge> {
|
||||
return realm.where(Challenge::class.java)
|
||||
.equalTo("id", id)
|
||||
|
|
@ -23,8 +43,12 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
|||
.map { it.first() }
|
||||
}
|
||||
|
||||
override fun getTasks(challenge: Challenge): Flowable<List<Task>> {
|
||||
return Flowable.empty()
|
||||
override fun getTasks(challengeID: String): Flowable<RealmResults<Task>> {
|
||||
return realm.where(Task::class.java)
|
||||
.equalTo("userId", challengeID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { realmObject -> realmObject.isLoaded }
|
||||
}
|
||||
|
||||
override val challenges: Flowable<RealmResults<Challenge>>
|
||||
|
|
@ -36,24 +60,45 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
|||
.filter { it.isLoaded }
|
||||
|
||||
override fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>> {
|
||||
return realm.where(Challenge::class.java)
|
||||
.isNotNull("name")
|
||||
.equalTo("isParticipating", true)
|
||||
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
||||
.findAllAsync()
|
||||
return realm.where(ChallengeMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.flatMap {
|
||||
val ids = it.map {
|
||||
return@map it.challengeID
|
||||
}.toTypedArray()
|
||||
realm.where(Challenge::class.java)
|
||||
.isNotNull("name")
|
||||
.`in`("id", ids)
|
||||
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
}
|
||||
|
||||
override fun setParticipating(challenge: Challenge, isParticipating: Boolean) {
|
||||
realm.executeTransaction { challenge.isParticipating = isParticipating }
|
||||
override fun setParticipating(userID: String, challengeID: String, isParticipating: Boolean) {
|
||||
if (isParticipating) {
|
||||
realm.executeTransaction {
|
||||
realm.insertOrUpdate(ChallengeMembership(userID, challengeID))
|
||||
}
|
||||
} else {
|
||||
val membership = realm.where(ChallengeMembership::class.java).equalTo("userID", userID).equalTo("challengeID", challengeID).findFirst()
|
||||
if (membership != null) {
|
||||
realm.executeTransaction {
|
||||
membership.deleteFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveChallenges(onlineChallenges: List<Challenge>) {
|
||||
override fun saveChallenges(challenges: List<Challenge>) {
|
||||
val localChallenges = realm.where(Challenge::class.java).findAll().createSnapshot()
|
||||
val challengesToDelete = ArrayList<Challenge>()
|
||||
for (localTask in localChallenges) {
|
||||
if (!onlineChallenges.contains(localTask)) {
|
||||
if (!challenges.contains(localTask)) {
|
||||
challengesToDelete.add(localTask)
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +107,6 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
|||
localTask.deleteFromRealm()
|
||||
}
|
||||
}
|
||||
realm.executeTransaction { realm1 -> realm1.insertOrUpdate(onlineChallenges) }
|
||||
realm.executeTransaction { realm1 -> realm1.insertOrUpdate(challenges) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.habitrpg.android.habitica.models.members.Member
|
|||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessageLike
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.models.social.GroupMembership
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
import io.realm.Realm
|
||||
|
|
@ -15,6 +16,35 @@ import java.util.*
|
|||
|
||||
class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), SocialLocalRepository {
|
||||
|
||||
override fun getGroupMembership(userId: String, id: String): Flowable<GroupMembership> = realm.where(GroupMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.equalTo("groupID", id)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.map { it.first() }
|
||||
|
||||
override fun getGroupMemberships(userId: String): Flowable<RealmResults<GroupMembership>> = realm.where(GroupMembership::class.java)
|
||||
.equalTo("userID", userId)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
|
||||
override fun updateMembership(userId: String, id: String, isMember: Boolean) {
|
||||
if (isMember) {
|
||||
realm.executeTransaction {
|
||||
realm.insertOrUpdate(GroupMembership(userId, id))
|
||||
}
|
||||
} else {
|
||||
val membership = realm.where(GroupMembership::class.java).equalTo("userID", userId).equalTo("groupID", id).findFirst()
|
||||
if (membership != null) {
|
||||
realm.executeTransaction {
|
||||
membership.deleteFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPublicGuilds(): Flowable<RealmResults<Group>> = realm.where(Group::class.java)
|
||||
.equalTo("type", "guild")
|
||||
.equalTo("privacy", "public")
|
||||
|
|
@ -23,13 +53,24 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
|
||||
override fun getUserGroups(): Flowable<RealmResults<Group>> = realm.where(Group::class.java)
|
||||
.equalTo("type", "guild")
|
||||
.equalTo("isMember", true)
|
||||
.sort("memberCount", Sort.DESCENDING)
|
||||
override fun getUserGroups(userID: String): Flowable<RealmResults<Group>> = realm.where(GroupMembership::class.java)
|
||||
.equalTo("userID", userID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
.flatMap {
|
||||
realm.where(Group::class.java)
|
||||
.equalTo("type", "guild")
|
||||
.`in`("id", it.map {
|
||||
return@map it.groupID
|
||||
}.toTypedArray())
|
||||
.sort("memberCount", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun getGroups(type: String): Flowable<RealmResults<Group>> {
|
||||
return realm.where(Group::class.java)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.habitrpg.android.habitica.data.local.UserLocalRepository
|
|||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import com.habitrpg.android.habitica.models.TutorialStep
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.Flowable
|
||||
|
|
@ -42,7 +42,7 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
removeOldTags(user.id, user.tags)
|
||||
}
|
||||
if (user.challenges != null) {
|
||||
removeOldChallenges(user.challenges)
|
||||
removeOldChallenges(user.id, user.challenges)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,12 +62,12 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
}
|
||||
|
||||
private fun removeOldChallenges(onlineChallenges: List<Challenge>) {
|
||||
val challenges = realm.where(Challenge::class.java).equalTo("isParticipating", true).findAll().createSnapshot()
|
||||
val challengesToDelete = challenges.filterNot { onlineChallenges.contains(it) }
|
||||
private fun removeOldChallenges(userID: String, onlineChallenges: List<ChallengeMembership>) {
|
||||
val memberships = realm.where(ChallengeMembership::class.java).equalTo("userID", userID).findAll().createSnapshot()
|
||||
val membershipsToDelete = memberships.filterNot { onlineChallenges.contains(it) }
|
||||
realm.executeTransaction {
|
||||
for (challenge in challengesToDelete) {
|
||||
challenge.isParticipating = false
|
||||
membershipsToDelete.forEach {
|
||||
it.deleteFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events.commands;
|
||||
|
||||
public class ShowChallengeDetailActivityCommand {
|
||||
public String challengeId;
|
||||
|
||||
public ShowChallengeDetailActivityCommand(String challengeId) {
|
||||
this.challengeId = challengeId;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events.commands;
|
||||
|
||||
public class ShowChallengeDetailDialogCommand {
|
||||
public String challengeId;
|
||||
|
||||
public ShowChallengeDetailDialogCommand(String challengeId) {
|
||||
this.challengeId = challengeId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.habitrpg.android.habitica.models.members;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.habitrpg.android.habitica.models.Avatar;
|
||||
import com.habitrpg.android.habitica.models.social.UserParty;
|
||||
|
|
@ -19,10 +21,15 @@ public class Member extends RealmObject implements Avatar {
|
|||
@SerializedName("_id")
|
||||
private String id;
|
||||
private Stats stats;
|
||||
@Nullable
|
||||
private Inbox inbox;
|
||||
@Nullable
|
||||
private MemberPreferences preferences;
|
||||
@Nullable
|
||||
private Profile profile;
|
||||
@Nullable
|
||||
private UserParty party;
|
||||
@Nullable
|
||||
private ContributorInfo contributor;
|
||||
|
||||
private Outfit costume;
|
||||
|
|
@ -73,6 +80,7 @@ public class Member extends RealmObject implements Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Stats getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
|
@ -84,6 +92,7 @@ public class Member extends RealmObject implements Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Inbox getInbox() {
|
||||
return inbox;
|
||||
}
|
||||
|
|
@ -95,6 +104,7 @@ public class Member extends RealmObject implements Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Profile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
|
@ -106,6 +116,7 @@ public class Member extends RealmObject implements Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ContributorInfo getContributor() {
|
||||
return contributor;
|
||||
}
|
||||
|
|
@ -117,6 +128,7 @@ public class Member extends RealmObject implements Avatar {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UserParty getParty() {
|
||||
return party;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
package com.habitrpg.android.habitica.models.social;
|
||||
|
||||
import com.habitrpg.android.habitica.models.tasks.ChecklistItem;
|
||||
import com.habitrpg.android.habitica.models.tasks.TasksOrder;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.realm.RealmObject;
|
||||
import io.realm.annotations.Ignore;
|
||||
import io.realm.annotations.PrimaryKey;
|
||||
|
||||
public class Challenge extends RealmObject {
|
||||
|
||||
public static final String TASK_ORDER_HABITS = "habits";
|
||||
public static final String TASK_ORDER_TODOS = "todos";
|
||||
public static final String TASK_ORDER_DAILYS = "dailys";
|
||||
public static final String TASK_ORDER_REWARDS = "rewards";
|
||||
|
||||
@PrimaryKey
|
||||
public String id;
|
||||
public String name;
|
||||
public String shortName;
|
||||
public String description;
|
||||
public String leaderName;
|
||||
public String leaderId;
|
||||
public String groupName;
|
||||
public String groupId;
|
||||
public int prize;
|
||||
public boolean official;
|
||||
public int memberCount;
|
||||
public String todoList;
|
||||
public String habitList;
|
||||
public String dailyList;
|
||||
public String rewardList;
|
||||
public Date createdAt;
|
||||
public Date updatedAt;
|
||||
|
||||
public Group group;
|
||||
|
||||
public User leader;
|
||||
@Ignore
|
||||
public TasksOrder tasksOrder;
|
||||
public boolean isParticipating;
|
||||
|
||||
public HashMap<String, String[]> getTasksOrder() {
|
||||
HashMap<String, String[]> map = new HashMap<>();
|
||||
|
||||
if (!dailyList.isEmpty()) {
|
||||
map.put(TASK_ORDER_DAILYS, dailyList.split(","));
|
||||
}
|
||||
|
||||
if (!habitList.isEmpty()) {
|
||||
map.put(TASK_ORDER_HABITS, habitList.split(","));
|
||||
}
|
||||
|
||||
if (!rewardList.isEmpty()) {
|
||||
map.put(TASK_ORDER_REWARDS, rewardList.split(","));
|
||||
}
|
||||
|
||||
if (!todoList.isEmpty()) {
|
||||
map.put(TASK_ORDER_TODOS, todoList.split(","));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj.getClass().equals(Challenge.class) && this.id != null) {
|
||||
return this.id.equals(((Challenge)obj).id);
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.habitrpg.android.habitica.models.social
|
||||
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.models.tasks.TasksOrder
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.Ignore
|
||||
import io.realm.annotations.PrimaryKey
|
||||
import java.util.*
|
||||
|
||||
open class Challenge : RealmObject() {
|
||||
|
||||
@PrimaryKey
|
||||
var id: String? = null
|
||||
var name: String? = null
|
||||
var shortName: String? = null
|
||||
var description: String? = null
|
||||
var leaderName: String? = null
|
||||
var leaderId: String? = null
|
||||
var groupName: String? = null
|
||||
var groupId: String? = null
|
||||
var prize: Int = 0
|
||||
var official: Boolean = false
|
||||
var memberCount: Int = 0
|
||||
var todoList: String? = null
|
||||
var habitList: String? = null
|
||||
var dailyList: String? = null
|
||||
var rewardList: String? = null
|
||||
var createdAt: Date? = null
|
||||
var updatedAt: Date? = null
|
||||
|
||||
var group: Group? = null
|
||||
|
||||
var leader: User? = null
|
||||
@Ignore
|
||||
var tasksOrder: TasksOrder? = null
|
||||
|
||||
fun getTasksOrder(): HashMap<String, Array<String>> {
|
||||
val map = HashMap<String, Array<String>>()
|
||||
|
||||
if (dailyList?.isNotEmpty() == true) {
|
||||
dailyList?.split(",".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray().notNull { map[TASK_ORDER_DAILYS] }
|
||||
}
|
||||
|
||||
if (habitList?.isNotEmpty() == true) {
|
||||
habitList?.split(",".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray().notNull { map[TASK_ORDER_HABITS] }
|
||||
}
|
||||
|
||||
if (rewardList?.isNotEmpty() == true) {
|
||||
rewardList?.split(",".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray().notNull { map[TASK_ORDER_REWARDS] }
|
||||
}
|
||||
|
||||
if (todoList?.isNotEmpty() == true) {
|
||||
todoList?.split(",".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray().notNull { map[TASK_ORDER_TODOS] }
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other?.javaClass == Challenge::class.java && this.id != null) {
|
||||
this.id == (other as Challenge).id
|
||||
} else super.equals(other)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TASK_ORDER_HABITS = "habits"
|
||||
const val TASK_ORDER_TODOS = "todos"
|
||||
const val TASK_ORDER_DAILYS = "dailys"
|
||||
const val TASK_ORDER_REWARDS = "rewards"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.habitrpg.android.habitica.models.social
|
||||
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
open class ChallengeMembership : RealmObject {
|
||||
@PrimaryKey
|
||||
var combinedID: String = ""
|
||||
|
||||
var userID: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
combinedID = userID + challengeID
|
||||
}
|
||||
var challengeID: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
combinedID = userID + challengeID
|
||||
}
|
||||
|
||||
constructor(userID: String, challengeID: String) : super() {
|
||||
this.userID = userID
|
||||
this.challengeID = challengeID
|
||||
}
|
||||
|
||||
constructor() : super()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other?.javaClass == ChallengeMembership::class.java) {
|
||||
this.combinedID == (other as ChallengeMembership).combinedID
|
||||
} else super.equals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = combinedID.hashCode()
|
||||
result = 31 * result + userID.hashCode()
|
||||
result = 31 * result + challengeID.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
@ -26,8 +26,6 @@ open class Group : RealmObject() {
|
|||
|
||||
var memberCount: Int = 0
|
||||
|
||||
var isMember: Boolean = false
|
||||
|
||||
var type: String? = null
|
||||
|
||||
var logo: String? = null
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.habitrpg.android.habitica.models.social
|
||||
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
open class GroupMembership : RealmObject {
|
||||
@PrimaryKey
|
||||
var combinedID: String = ""
|
||||
|
||||
var userID: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
combinedID = userID + groupID
|
||||
}
|
||||
var groupID: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
combinedID = userID + groupID
|
||||
}
|
||||
|
||||
constructor(userID: String, groupID: String) : super() {
|
||||
this.userID = userID
|
||||
this.groupID = groupID
|
||||
}
|
||||
|
||||
constructor() : super()
|
||||
}
|
||||
|
|
@ -85,6 +85,19 @@ open class Task : RealmObject, Parcelable {
|
|||
val completedChecklistCount: Int
|
||||
get() = checklist?.count { it.completed } ?: 0
|
||||
|
||||
val extraLightTaskColor: Int
|
||||
get() {
|
||||
return when {
|
||||
this.value < -20 -> return R.color.maroon_500
|
||||
this.value < -10 -> return R.color.red_500
|
||||
this.value < -1 -> return R.color.orange_500
|
||||
this.value < 1 -> return R.color.yellow_500
|
||||
this.value < 5 -> return R.color.green_500
|
||||
this.value < 10 -> return R.color.teal_500
|
||||
else -> R.color.blue_500
|
||||
}
|
||||
}
|
||||
|
||||
val lightTaskColor: Int
|
||||
get() {
|
||||
return when {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.habitrpg.android.habitica.models.PushDevice;
|
|||
import com.habitrpg.android.habitica.models.Tag;
|
||||
import com.habitrpg.android.habitica.models.invitations.Invitations;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership;
|
||||
import com.habitrpg.android.habitica.models.social.UserParty;
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList;
|
||||
import com.habitrpg.android.habitica.models.tasks.TasksOrder;
|
||||
|
|
@ -51,7 +52,7 @@ public class User extends RealmObject implements Avatar {
|
|||
@Ignore
|
||||
private TasksOrder tasksOrder;
|
||||
|
||||
private RealmList<Challenge> challenges;
|
||||
private RealmList<ChallengeMembership> challenges;
|
||||
|
||||
private Date lastCron;
|
||||
private Boolean needsCron;
|
||||
|
|
@ -310,11 +311,11 @@ public class User extends RealmObject implements Avatar {
|
|||
this.tags = tags;
|
||||
}
|
||||
|
||||
public RealmList<Challenge> getChallenges() {
|
||||
public RealmList<ChallengeMembership> getChallenges() {
|
||||
return challenges;
|
||||
}
|
||||
|
||||
public void setChallenges(RealmList<Challenge> challenges) {
|
||||
public void setChallenges(RealmList<ChallengeMembership> challenges) {
|
||||
this.challenges = challenges;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ public class RepositoryModule {
|
|||
}
|
||||
|
||||
@Provides
|
||||
ChallengeRepository providesChallengeRepository(ChallengeLocalRepository localRepository, ApiClient apiClient) {
|
||||
return new ChallengeRepositoryImpl(localRepository, apiClient);
|
||||
ChallengeRepository providesChallengeRepository(ChallengeLocalRepository localRepository, ApiClient apiClient, @Named(AppModule.NAMED_USER_ID) String userId) {
|
||||
return new ChallengeRepositoryImpl(localRepository, apiClient, userId);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -1,397 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TabLayout
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.HabitScoreEvent
|
||||
import com.habitrpg.android.habitica.events.TaskUpdatedEvent
|
||||
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand
|
||||
import com.habitrpg.android.habitica.events.commands.ChecklistCheckedCommand
|
||||
import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.interactors.*
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody
|
||||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeDetailDialogHolder
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.utils.Action1
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiParser
|
||||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
|
||||
class ChallengeDetailActivity : BaseActivity() {
|
||||
|
||||
|
||||
@Inject
|
||||
internal lateinit var challengeRepository: ChallengeRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
internal lateinit var userId: String
|
||||
@Inject
|
||||
internal lateinit var userRepository: UserRepository
|
||||
|
||||
private val floatingMenuWrapper: FrameLayout by bindView(R.id.floating_menu_wrapper)
|
||||
private val detailTabs: TabLayout by bindView(R.id.detail_tabs)
|
||||
private val toolbar: Toolbar by bindView(R.id.toolbar)
|
||||
// region UseCases
|
||||
|
||||
@Inject
|
||||
internal lateinit var habitScoreUseCase: HabitScoreUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var dailyCheckUseCase: DailyCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var todoCheckUseCase: TodoCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var buyRewardUseCase: BuyRewardUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var checklistCheckUseCase: ChecklistCheckUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var displayItemDropUseCase: DisplayItemDropUseCase
|
||||
|
||||
@Inject
|
||||
internal lateinit var notifyUserUseCase: NotifyUserUseCase
|
||||
|
||||
// endregion
|
||||
|
||||
private var challenge: Challenge? = null
|
||||
private var user: User? = null
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.activity_challenge_detail
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
val inflater = menuInflater
|
||||
inflater.inflate(R.menu.menu_challenge_details, menu)
|
||||
|
||||
if (challenge?.leaderId != userId) {
|
||||
menu.setGroupVisible(R.id.challenge_edit_action_group, false)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setupToolbar(toolbar)
|
||||
|
||||
supportActionBar?.setTitle(R.string.challenge_details)
|
||||
detailTabs.visibility = View.GONE
|
||||
|
||||
val extras = intent.extras
|
||||
|
||||
val challengeId = extras.getString(CHALLENGE_ID)
|
||||
|
||||
val fullList = ArrayList<Task>()
|
||||
|
||||
userRepository.getUser(userId).firstElement().subscribe(Consumer { user ->
|
||||
this@ChallengeDetailActivity.user = user
|
||||
createTaskRecyclerFragment(fullList)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallengeTasks(challengeId)
|
||||
.firstElement()
|
||||
.subscribe(Consumer { taskList ->
|
||||
val resultList = ArrayList<Task>()
|
||||
|
||||
val todos = ArrayList<Task>()
|
||||
val habits = ArrayList<Task>()
|
||||
val dailies = ArrayList<Task>()
|
||||
val rewards = ArrayList<Task>()
|
||||
|
||||
for (entry in taskList.tasks.entries) {
|
||||
when (entry.value.type) {
|
||||
Task.TYPE_TODO -> todos.add(entry.value)
|
||||
Task.TYPE_HABIT ->
|
||||
|
||||
habits.add(entry.value)
|
||||
Task.TYPE_DAILY ->
|
||||
|
||||
dailies.add(entry.value)
|
||||
Task.TYPE_REWARD ->
|
||||
|
||||
rewards.add(entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!habits.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divhabits"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Habits"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(habits)
|
||||
}
|
||||
|
||||
|
||||
if (!dailies.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divdailies"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Dailies"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(dailies)
|
||||
}
|
||||
|
||||
|
||||
if (!todos.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divtodos"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge To-Dos"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(todos)
|
||||
}
|
||||
|
||||
if (!rewards.isEmpty()) {
|
||||
val dividerTask = Task()
|
||||
dividerTask.id = "divrewards"
|
||||
dividerTask.type = "divider"
|
||||
dividerTask.text = "Challenge Rewards"
|
||||
|
||||
resultList.add(dividerTask)
|
||||
resultList.addAll(rewards)
|
||||
}
|
||||
|
||||
|
||||
fullList.addAll(resultList)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
if (challengeId != null) {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(Consumer { challenge ->
|
||||
this@ChallengeDetailActivity.challenge = challenge
|
||||
val challengeViewHolder = ChallengeViewHolder(findViewById(R.id.challenge_header))
|
||||
challengeViewHolder.bind(challenge)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTaskRecyclerFragment(fullList: List<Task>) {
|
||||
val fragment = ChallengeTasksRecyclerViewFragment.newInstance(user, fullList)
|
||||
|
||||
if (supportFragmentManager.fragments == null) {
|
||||
supportFragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commitAllowingStateLoss()
|
||||
} else {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
transaction.replace(R.id.fragment_container, fragment).addToBackStack(null).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
challengeRepository.close()
|
||||
userRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectActivity(component: AppComponent?) {
|
||||
component?.inject(this)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_edit -> {
|
||||
openChallengeEditActivity()
|
||||
return true
|
||||
}
|
||||
R.id.action_leave -> {
|
||||
showChallengeLeaveDialog()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun openChallengeEditActivity() {
|
||||
val intent = Intent(this, CreateChallengeActivity::class.java)
|
||||
intent.putExtra(CreateChallengeActivity.CHALLENGE_ID_KEY, challenge?.id)
|
||||
|
||||
startActivity(intent)
|
||||
|
||||
}
|
||||
|
||||
private fun showChallengeLeaveDialog() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_leave_title))
|
||||
.setMessage(this.getString(R.string.challenge_leave_text, challenge?.name ?: ""))
|
||||
.setPositiveButton(this.getString(R.string.yes)) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
|
||||
showRemoveTasksDialog(object: Action1<String> {
|
||||
override fun call(t: String) {
|
||||
challengeRepository.leaveChallenge(challenge, LeaveChallengeBody(t))
|
||||
.subscribe(Consumer { finish() }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
})
|
||||
}
|
||||
.setNegativeButton(this.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }.show()
|
||||
}
|
||||
|
||||
// refactor as an UseCase later - see ChallengeDetailDialogHolder
|
||||
private fun showRemoveTasksDialog(callback: Action1<String>) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(this.getString(R.string.challenge_remove_tasks_title))
|
||||
.setMessage(this.getString(R.string.challenge_remove_tasks_text))
|
||||
.setPositiveButton(this.getString(R.string.remove_tasks)) { dialog, _ ->
|
||||
callback.call("remove-all")
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(this.getString(R.string.keep_tasks)) { dialog, _ ->
|
||||
callback.call("keep-all")
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finish()
|
||||
}
|
||||
|
||||
internal inner class ChallengeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val challengeName: EmojiTextView by bindView(itemView, R.id.challenge_name)
|
||||
private val challengeDescription: EmojiTextView by bindView(itemView, R.id.challenge_description)
|
||||
private val memberCountTextView: TextView by bindView(itemView, R.id.challenge_member_count)
|
||||
private val gemPrizeTextView: TextView by bindView(itemView, R.id.gem_amount)
|
||||
private val showMoreButton: Button by bindView(itemView, R.id.btn_show_more)
|
||||
|
||||
private var challenge: Challenge? = null
|
||||
|
||||
init {
|
||||
showMoreButton.setOnClickListener { onShowMore() }
|
||||
|
||||
val gemDrawable = BitmapDrawable(itemView.resources, HabiticaIconsHelper.imageOfGem())
|
||||
gemPrizeTextView.setCompoundDrawablesWithIntrinsicBounds(gemDrawable, null, null, null)
|
||||
}
|
||||
|
||||
fun bind(challenge: Challenge) {
|
||||
this.challenge = challenge
|
||||
|
||||
challengeName.text = EmojiParser.parseEmojis(challenge.name)
|
||||
challengeDescription.text = MarkdownParser.parseMarkdown(challenge.description)
|
||||
|
||||
memberCountTextView.text = challenge.memberCount.toString()
|
||||
|
||||
if (challenge.prize == 0) {
|
||||
gemPrizeTextView.visibility = View.GONE
|
||||
} else {
|
||||
gemPrizeTextView.visibility = View.VISIBLE
|
||||
gemPrizeTextView.text = challenge.prize.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun onShowMore() {
|
||||
challenge.notNull {
|
||||
ChallengeDetailDialogHolder.showDialog(this@ChallengeDetailActivity,
|
||||
this@ChallengeDetailActivity.challengeRepository,
|
||||
it,
|
||||
object: Action1<Challenge> {
|
||||
override fun call(t: Challenge) {
|
||||
onBackPressed()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: TaskCheckedCommand) {
|
||||
when (event.Task.type) {
|
||||
Task.TYPE_DAILY -> {
|
||||
dailyCheckUseCase.observable(DailyCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
todoCheckUseCase.observable(TodoCheckUseCase.RequestValues(user, event.Task, !event.Task.completed))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: ChecklistCheckedCommand) {
|
||||
checklistCheckUseCase.observable(ChecklistCheckUseCase.RequestValues(event.task.id, event.item.id))
|
||||
.subscribe(Consumer { EventBus.getDefault().post(TaskUpdatedEvent(event.task)) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: HabitScoreEvent) {
|
||||
habitScoreUseCase.observable(HabitScoreUseCase.RequestValues(user, event.habit, event.Up))
|
||||
.subscribe(Consumer { this.onTaskDataReceived(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: BuyRewardCommand) {
|
||||
if ((user?.stats?.gp ?: 0.toDouble()) < event.Reward.value) {
|
||||
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.no_gold), HabiticaSnackbar.SnackbarDisplayType.FAILURE)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (event.Reward.specialTag == null || event.Reward.specialTag != "item") {
|
||||
|
||||
buyRewardUseCase.observable(BuyRewardUseCase.RequestValues(user, event.Reward))
|
||||
.subscribe(Consumer { HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_purchase_reward), HabiticaSnackbar.SnackbarDisplayType.NORMAL) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun onTaskDataReceived(data: TaskScoringResult) {
|
||||
if (user != null) {
|
||||
notifyUserUseCase.observable(NotifyUserUseCase.RequestValues(this, floatingMenuWrapper,
|
||||
user, data.experienceDelta, data.healthDelta, data.goldDelta, data.manaDelta, data.questDamage, data.hasLeveledUp))
|
||||
}
|
||||
|
||||
displayItemDropUseCase.observable(DisplayItemDropUseCase.RequestValues(data, this, floatingMenuWrapper))
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var CHALLENGE_ID = "CHALLENGE_ID"
|
||||
}
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ class CreateChallengeActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun fillControlsByChallenge() {
|
||||
challengeRepository.getChallenge(challengeId).subscribe(Consumer { challenge ->
|
||||
/*challengeRepository.getChallenge(challengeId).subscribe(Consumer { challenge ->
|
||||
|
||||
createChallengeTitle.setText(challenge.name)
|
||||
createChallengeDescription.setText(challenge.description)
|
||||
|
|
@ -377,13 +377,7 @@ class CreateChallengeActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
checkPrizeAndMinimumForTavern()
|
||||
|
||||
challengeRepository.getChallengeTasks(challengeId).doOnComplete { editMode = true }.subscribe(Consumer { tasks ->
|
||||
for (task in tasks.tasks.values) {
|
||||
addOrUpdateTaskInList(task)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}, RxErrorHandler.handleEmptyError())*/
|
||||
}
|
||||
|
||||
private fun openNewTaskActivity(type: String?, task: Task?) {
|
||||
|
|
|
|||
|
|
@ -156,6 +156,10 @@ class FullProfileActivity : BaseActivity() {
|
|||
private fun updateView(user: Member) {
|
||||
val profile = user.profile
|
||||
|
||||
if (profile == null) {
|
||||
return
|
||||
}
|
||||
|
||||
userName = profile.name
|
||||
|
||||
title = profile.name
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ import android.widget.ImageView
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand
|
||||
import com.habitrpg.android.habitica.extensions.inflate
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeFilterOptions
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.playseeds.android.sdk.inappmessaging.Log
|
||||
import io.reactivex.BackpressureStrategy
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import io.realm.OrderedRealmCollection
|
||||
import io.realm.RealmRecyclerViewAdapter
|
||||
import net.pherth.android.emoji_library.EmojiParser
|
||||
|
|
@ -25,13 +27,22 @@ import org.greenrobot.eventbus.EventBus
|
|||
class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUpdate: Boolean, private val viewUserChallengesOnly: Boolean, private val userId: String) : RealmRecyclerViewAdapter<Challenge, ChallengesListViewAdapter.ChallengeViewHolder>(data, autoUpdate) {
|
||||
private var unfilteredData: OrderedRealmCollection<Challenge>? = null
|
||||
|
||||
private val openChallengeFragmentEvents = PublishSubject.create<String>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChallengeViewHolder {
|
||||
return ChallengeViewHolder(parent.inflate(R.layout.challenge_item), viewUserChallengesOnly)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ChallengeViewHolder, position: Int) {
|
||||
data.notNull {
|
||||
holder.bind(it[position])
|
||||
data?.get(position).notNull { challenge ->
|
||||
holder.bind(challenge)
|
||||
holder.itemView.setOnClickListener {
|
||||
if (challenge.isManaged) {
|
||||
challenge.id.notNull {
|
||||
openChallengeFragmentEvents.onNext(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +81,11 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
|
|||
}
|
||||
}
|
||||
|
||||
class ChallengeViewHolder internal constructor(itemView: View, private val viewUserChallengesOnly: Boolean) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
fun getOpenDetailFragmentFlowable(): Flowable<String> {
|
||||
return openChallengeFragmentEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
class ChallengeViewHolder internal constructor(itemView: View, private val viewUserChallengesOnly: Boolean) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
private val challengeName: EmojiTextView by bindView(R.id.challenge_name)
|
||||
private val challengeDescription: TextView by bindView(R.id.challenge_group_name)
|
||||
|
|
@ -87,8 +102,6 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
|
|||
private var challenge: Challenge? = null
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
|
||||
gemIconView.setImageBitmap(HabiticaIconsHelper.imageOfGem())
|
||||
|
||||
if (!viewUserChallengesOnly) {
|
||||
|
|
@ -99,7 +112,8 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
|
|||
fun bind(challenge: Challenge) {
|
||||
this.challenge = challenge
|
||||
|
||||
challengeName.text = EmojiParser.parseEmojis(challenge.name.trim { it <= ' ' })
|
||||
Log.e(challenge.id + challenge.name)
|
||||
challengeName.text = EmojiParser.parseEmojis(challenge.name?.trim { it <= ' ' })
|
||||
challengeDescription.text = challenge.groupName
|
||||
|
||||
officialChallengeLayout.visibility = if (challenge.official) View.VISIBLE else View.GONE
|
||||
|
|
@ -109,7 +123,7 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
|
|||
challengeParticipatingTextView.visibility = View.GONE
|
||||
arrowImage.visibility = View.VISIBLE
|
||||
} else {
|
||||
challengeParticipatingTextView.visibility = if (challenge.isParticipating) View.VISIBLE else View.GONE
|
||||
//challengeParticipatingTextView.visibility = if (challenge.isParticipating) View.VISIBLE else View.GONE
|
||||
|
||||
leaderName.text = itemView.context.getString(R.string.byLeader, challenge.leaderName)
|
||||
participantCount.text = challenge.memberCount.toString()
|
||||
|
|
@ -119,15 +133,5 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
|
|||
|
||||
gemPrizeTextView.text = challenge.prize.toString()
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
if (challenge != null && challenge!!.isManaged && challenge!!.isManaged) {
|
||||
if (viewUserChallengesOnly) {
|
||||
EventBus.getDefault().post(ShowChallengeDetailActivityCommand(challenge!!.id))
|
||||
} else {
|
||||
EventBus.getDefault().post(ShowChallengeDetailDialogCommand(challenge!!.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, auto
|
|||
else -> R.color.task_gray
|
||||
}
|
||||
ViewHelper.SetBackgroundTint(classBackground, ContextCompat.getColor(itemView.context, colorResourceID))
|
||||
userName.text = user.profile.name
|
||||
userName.text = user.profile?.name
|
||||
|
||||
itemView.isClickable = true
|
||||
itemView.setOnClickListener { userClickedEvents.onNext(user.id) }
|
||||
|
|
|
|||
|
|
@ -82,9 +82,12 @@ class StatsFragment: BaseMainFragment() {
|
|||
|
||||
leftSparklesView.setImageBitmap(HabiticaIconsHelper.imageOfAttributeSparklesLeft())
|
||||
rightSparklesView.setImageBitmap(HabiticaIconsHelper.imageOfAttributeSparklesRight())
|
||||
distributeEvenlyHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon())
|
||||
distributeClassHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon())
|
||||
distributeTaskHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon())
|
||||
context.notNull {
|
||||
val color = ContextCompat.getColor(it, R.color.brand_200)
|
||||
distributeEvenlyHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon(color))
|
||||
distributeClassHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon(color))
|
||||
distributeTaskHelpButton.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon(color))
|
||||
}
|
||||
|
||||
compositeSubscription.add(userRepository.getUser(userId).subscribe(Consumer {
|
||||
user = it
|
||||
|
|
|
|||
|
|
@ -1,307 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.LeaveChallengeBody
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.FullProfileActivity
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.utils.Action1
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiParser
|
||||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import java.util.*
|
||||
|
||||
class ChallengeDetailDialogHolder private constructor(view: View, private val context: Activity) {
|
||||
|
||||
private val notJoinedHeader: LinearLayout? by bindView(view, R.id.challenge_not_joined_header)
|
||||
private val joinedHeader: LinearLayout? by bindView(view, R.id.challenge_joined_header)
|
||||
private val joinButton: Button? by bindView(view, R.id.challenge_join_btn)
|
||||
private val leaveButton: Button? by bindView(view, R.id.challenge_leave_btn)
|
||||
private val challengeName: EmojiTextView? by bindView(view, R.id.challenge_name)
|
||||
private val challengeDescription: EmojiTextView? by bindView(view, R.id.challenge_description)
|
||||
private val challengeLeader: TextView? by bindView(view, R.id.challenge_leader)
|
||||
private val gemAmountView: TextView? by bindView(view, R.id.gem_amount)
|
||||
private val memberCountView: TextView? by bindView(view, R.id.challenge_member_count)
|
||||
private val taskGrouplayout: LinearLayout? by bindView(view, R.id.task_group_layout)
|
||||
private val openChallengeButton: Button? by bindView(view, R.id.challenge_go_to_btn)
|
||||
|
||||
private var dialog: AlertDialog? = null
|
||||
lateinit var challengeRepository: ChallengeRepository
|
||||
private var challenge: Challenge? = null
|
||||
private var challengeLeftAction: Action1<Challenge>? = null
|
||||
|
||||
init {
|
||||
joinButton?.setOnClickListener { joinChallenge() }
|
||||
leaveButton?.setOnClickListener { leaveChallenge() }
|
||||
challengeLeader?.setOnClickListener { openLeaderProfile() }
|
||||
openChallengeButton?.setOnClickListener { openChallengeActivity() }
|
||||
}
|
||||
|
||||
fun bind(dialog: AlertDialog, challengeRepository: ChallengeRepository, challenge: Challenge,
|
||||
challengeLeftAction: Action1<Challenge>) {
|
||||
this.dialog = dialog
|
||||
this.challengeRepository = challengeRepository
|
||||
this.challenge = challenge
|
||||
this.challengeLeftAction = challengeLeftAction
|
||||
|
||||
changeViewsByChallenge(challenge)
|
||||
}
|
||||
|
||||
private fun changeViewsByChallenge(challenge: Challenge) {
|
||||
setJoined(challenge.isParticipating)
|
||||
|
||||
challengeName?.text = EmojiParser.parseEmojis(challenge.name)
|
||||
challengeDescription?.text = MarkdownParser.parseMarkdown(challenge.description)
|
||||
challengeLeader?.text = challenge.leaderName
|
||||
|
||||
gemAmountView?.text = challenge.prize.toString()
|
||||
memberCountView?.text = challenge.memberCount.toString()
|
||||
|
||||
challengeRepository.getChallengeTasks(challenge.id)
|
||||
.subscribe(Consumer { taskList ->
|
||||
val todos = ArrayList<Task>()
|
||||
val habits = ArrayList<Task>()
|
||||
val dailies = ArrayList<Task>()
|
||||
val rewards = ArrayList<Task>()
|
||||
|
||||
for (entry in taskList.tasks.entries) {
|
||||
when (entry.value.type) {
|
||||
Task.TYPE_TODO -> todos.add(entry.value)
|
||||
Task.TYPE_HABIT ->
|
||||
|
||||
habits.add(entry.value)
|
||||
Task.TYPE_DAILY ->
|
||||
|
||||
dailies.add(entry.value)
|
||||
Task.TYPE_REWARD ->
|
||||
|
||||
rewards.add(entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
if (habits.size > 0) {
|
||||
addHabits(habits)
|
||||
}
|
||||
|
||||
if (dailies.size > 0) {
|
||||
addDailys(dailies)
|
||||
}
|
||||
|
||||
if (todos.size > 0) {
|
||||
addTodos(todos)
|
||||
}
|
||||
|
||||
if (rewards.size > 0) {
|
||||
addRewards(rewards)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun addHabits(habits: ArrayList<Task>) {
|
||||
val taskGroup = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_task_group, taskGrouplayout, false) as LinearLayout
|
||||
val groupName = taskGroup.findViewById<View>(R.id.task_group_name) as TextView
|
||||
|
||||
val tasksLayout = taskGroup.findViewById<View>(R.id.tasks_layout) as LinearLayout
|
||||
|
||||
groupName.text = habits.size.toString() + " " + getLabelByTypeAndCount(Challenge.TASK_ORDER_HABITS, habits.size)
|
||||
|
||||
val size = habits.size
|
||||
for (i in 0 until size) {
|
||||
val task = habits[i]
|
||||
|
||||
val entry = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_habit, tasksLayout, false)
|
||||
val habitTitle = entry.findViewById<View>(R.id.habit_title) as TextView
|
||||
val plusImg = entry.findViewById<View>(if (task.up == true) R.id.plus_img_tinted else R.id.plus_img) as ImageView
|
||||
val minusImg = entry.findViewById<View>(if (task.down == true) R.id.minus_img_tinted else R.id.minus_img) as ImageView
|
||||
|
||||
plusImg.visibility = View.VISIBLE
|
||||
minusImg.visibility = View.VISIBLE
|
||||
|
||||
habitTitle.text = EmojiParser.parseEmojis(task.text)
|
||||
tasksLayout.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addDailys(dailies: ArrayList<Task>) {
|
||||
val taskGroup = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_task_group, taskGrouplayout, false) as LinearLayout
|
||||
val groupName = taskGroup.findViewById<View>(R.id.task_group_name) as TextView
|
||||
|
||||
val tasksLayout = taskGroup.findViewById<View>(R.id.tasks_layout) as LinearLayout
|
||||
|
||||
val size = dailies.size
|
||||
groupName.text = dailies.size.toString() + " " + getLabelByTypeAndCount(Challenge.TASK_ORDER_DAILYS, size)
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = dailies[i]
|
||||
|
||||
val entry = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_daily, tasksLayout, false)
|
||||
val title = entry.findViewById<View>(R.id.daily_title) as TextView
|
||||
title.text = EmojiParser.parseEmojis(task.text)
|
||||
|
||||
if (task.checklist != null && task.checklist?.isEmpty() == false) {
|
||||
val checklistIndicatorWrapper = entry.findViewById<View>(R.id.checklistIndicatorWrapper)
|
||||
|
||||
checklistIndicatorWrapper.visibility = View.VISIBLE
|
||||
|
||||
val checkListAllTextView = entry.findViewById<View>(R.id.checkListAllTextView) as TextView
|
||||
checkListAllTextView.text = task.checklist?.size.toString()
|
||||
}
|
||||
tasksLayout.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addTodos(todos: ArrayList<Task>) {
|
||||
val taskGroup = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_task_group, taskGrouplayout, false) as LinearLayout
|
||||
val groupName = taskGroup.findViewById<View>(R.id.task_group_name) as TextView
|
||||
|
||||
val tasksLayout = taskGroup.findViewById<View>(R.id.tasks_layout) as LinearLayout
|
||||
|
||||
val size = todos.size
|
||||
groupName.text = todos.size.toString() + " " + getLabelByTypeAndCount(Challenge.TASK_ORDER_TODOS, size)
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = todos[i]
|
||||
|
||||
val entry = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_todo, tasksLayout, false)
|
||||
val title = entry.findViewById<View>(R.id.todo_title) as TextView
|
||||
title.text = EmojiParser.parseEmojis(task.text)
|
||||
|
||||
if (task.checklist != null && task.checklist?.isEmpty() == false) {
|
||||
val checklistIndicatorWrapper = entry.findViewById<View>(R.id.checklistIndicatorWrapper)
|
||||
|
||||
checklistIndicatorWrapper.visibility = View.VISIBLE
|
||||
|
||||
val checkListAllTextView = entry.findViewById<View>(R.id.checkListAllTextView) as TextView
|
||||
checkListAllTextView.text = task.checklist?.size.toString()
|
||||
}
|
||||
tasksLayout.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addRewards(rewards: ArrayList<Task>) {
|
||||
val taskGroup = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_task_group, taskGrouplayout, false) as LinearLayout
|
||||
val groupName = taskGroup.findViewById<View>(R.id.task_group_name) as TextView
|
||||
|
||||
val tasksLayout = taskGroup.findViewById<View>(R.id.tasks_layout) as LinearLayout
|
||||
|
||||
val size = rewards.size
|
||||
groupName.text = rewards.size.toString() + " " + getLabelByTypeAndCount(Challenge.TASK_ORDER_REWARDS, size)
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = rewards[i]
|
||||
|
||||
val entry = context.layoutInflater.inflate(R.layout.dialog_challenge_detail_reward, tasksLayout, false)
|
||||
(entry.findViewById<View>(R.id.gold_icon) as ImageView).setImageBitmap(HabiticaIconsHelper.imageOfGold())
|
||||
val title = entry.findViewById<View>(R.id.reward_title) as TextView
|
||||
title.text = EmojiParser.parseEmojis(task.text)
|
||||
tasksLayout.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun getLabelByTypeAndCount(type: String, count: Int): String {
|
||||
return when (type) {
|
||||
Challenge.TASK_ORDER_DAILYS -> context.getString(if (count == 1) R.string.daily else R.string.dailies)
|
||||
Challenge.TASK_ORDER_HABITS -> context.getString(if (count == 1) R.string.habit else R.string.habits)
|
||||
Challenge.TASK_ORDER_REWARDS -> context.getString(if (count == 1) R.string.reward else R.string.rewards)
|
||||
else -> context.getString(if (count == 1) R.string.todo else R.string.todos)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setJoined(joined: Boolean) {
|
||||
joinedHeader?.visibility = if (joined) View.VISIBLE else View.GONE
|
||||
leaveButton?.visibility = if (joined) View.VISIBLE else View.GONE
|
||||
|
||||
notJoinedHeader?.visibility = if (joined) View.GONE else View.VISIBLE
|
||||
joinButton?.visibility = if (joined) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
private fun openLeaderProfile() {
|
||||
FullProfileActivity.open(context, challenge?.leaderId ?: "")
|
||||
}
|
||||
|
||||
private fun openChallengeActivity() {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(ChallengeDetailActivity.CHALLENGE_ID, challenge?.id)
|
||||
|
||||
val intent = Intent(context, ChallengeDetailActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
context.startActivity(intent)
|
||||
this.dialog?.dismiss()
|
||||
}
|
||||
|
||||
private fun joinChallenge() {
|
||||
this.challengeRepository.joinChallenge(challenge).subscribe(Consumer<Challenge> { this.changeViewsByChallenge(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun leaveChallenge() {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.getString(R.string.challenge_leave_title))
|
||||
.setMessage(context.getString(R.string.challenge_leave_text, challenge?.name))
|
||||
.setPositiveButton(context.getString(R.string.yes)) { dialog, _ ->
|
||||
showRemoveTasksDialog(object : Action1<String> {
|
||||
override fun call(t: String) {
|
||||
challengeRepository.leaveChallenge(challenge, LeaveChallengeBody(t))
|
||||
.subscribe(Consumer {
|
||||
challenge.notNull {
|
||||
challengeLeftAction?.call(it)
|
||||
}
|
||||
dialog.dismiss()
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
})
|
||||
}
|
||||
.setNegativeButton(context.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }.show()
|
||||
}
|
||||
|
||||
// refactor as an UseCase later - see ChallengeDetailActivity
|
||||
private fun showRemoveTasksDialog(callback: Action1<String>) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.getString(R.string.challenge_remove_tasks_title))
|
||||
.setMessage(context.getString(R.string.challenge_remove_tasks_text))
|
||||
.setPositiveButton(context.getString(R.string.remove_tasks)) { dialog, _ ->
|
||||
callback.call("remove-all")
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(context.getString(R.string.keep_tasks)) { dialog, _ ->
|
||||
callback.call("keep-all")
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun showDialog(activity: Activity?, challengeRepository: ChallengeRepository, challenge: Challenge, challengeLeftAction: Action1<Challenge>) {
|
||||
if (activity == null) {
|
||||
return
|
||||
}
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_challenge_detail, null)
|
||||
|
||||
val challengeDetailDialogHolder = ChallengeDetailDialogHolder(dialogLayout, activity)
|
||||
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
.setView(dialogLayout)
|
||||
|
||||
challengeDetailDialogHolder.bind(builder.show(), challengeRepository, challenge, challengeLeftAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.extensions.inflate
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.social.UsernameLabel
|
||||
import io.reactivex.functions.Action
|
||||
import io.reactivex.functions.Consumer
|
||||
import net.pherth.android.emoji_library.EmojiParser
|
||||
import net.pherth.android.emoji_library.EmojiTextView
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
|
||||
|
||||
class ChallengeDetailFragment: BaseMainFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var challengeRepository: ChallengeRepository
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
private val joinButtonWrapper: ViewGroup? by bindView(R.id.join_button_wrapper)
|
||||
private val joinButton: Button? by bindView(R.id.join_button)
|
||||
private val leaveButonWrapper: ViewGroup? by bindView(R.id.leave_button_wrapper)
|
||||
private val leaveButton: Button? by bindView(R.id.leave_button)
|
||||
private val challengeName: EmojiTextView? by bindView(R.id.challenge_name)
|
||||
private val challengeDescription: EmojiTextView? by bindView(R.id.challenge_description)
|
||||
private val challengeLeaderAvatarView: AvatarView? by bindView(R.id.creator_avatarview)
|
||||
private val challengeLeaderLabel: UsernameLabel? by bindView(R.id.creator_label)
|
||||
private val gemAmountView: TextView? by bindView(R.id.gem_amount)
|
||||
private val gemAmountIconView: ImageView? by bindView(R.id.gem_amount_icon)
|
||||
private val memberCountView: TextView? by bindView(R.id.participant_count)
|
||||
private val memberCountIconView: ImageView? by bindView(R.id.participant_count_icon)
|
||||
private val taskGrouplayout: LinearLayout? by bindView(R.id.task_group_layout)
|
||||
|
||||
var challengeID: String? = null
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
return container?.inflate(R.layout.fragment_challenge_detail)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
gemAmountIconView?.setImageBitmap(HabiticaIconsHelper.imageOfGem_36())
|
||||
memberCountIconView?.setImageBitmap(HabiticaIconsHelper.imageOfParticipantIcon())
|
||||
|
||||
challengeID.notNull {
|
||||
compositeSubscription.add(challengeRepository.getChallenge(it)
|
||||
.doOnNext {
|
||||
set(it)
|
||||
}
|
||||
.map {
|
||||
return@map (it.leaderId ?: "")
|
||||
}
|
||||
.flatMap { creatorID ->
|
||||
return@flatMap socialRepository.getMember(creatorID)
|
||||
}
|
||||
.subscribe(Consumer { set(it)}, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(challengeRepository.getChallengeTasks(it).subscribe(Consumer { taskList ->
|
||||
taskGrouplayout?.removeAllViewsInLayout()
|
||||
|
||||
val todos = ArrayList<Task>()
|
||||
val habits = ArrayList<Task>()
|
||||
val dailies = ArrayList<Task>()
|
||||
val rewards = ArrayList<Task>()
|
||||
|
||||
for (entry in taskList) {
|
||||
when (entry.type) {
|
||||
Task.TYPE_TODO -> todos.add(entry)
|
||||
Task.TYPE_HABIT -> habits.add(entry)
|
||||
Task.TYPE_DAILY -> dailies.add(entry)
|
||||
Task.TYPE_REWARD -> rewards.add(entry)
|
||||
}
|
||||
}
|
||||
|
||||
if (habits.size > 0) {
|
||||
addHabits(habits)
|
||||
}
|
||||
|
||||
if (dailies.size > 0) {
|
||||
addDailys(dailies)
|
||||
}
|
||||
|
||||
if (todos.size > 0) {
|
||||
addTodos(todos)
|
||||
}
|
||||
|
||||
if (rewards.size > 0) {
|
||||
addRewards(rewards)
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
|
||||
compositeSubscription.add(challengeRepository.isChallengeMember(it).subscribe(Consumer { isMember ->
|
||||
setJoined(isMember)
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
refresh()
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
challengeID.notNull {id ->
|
||||
challengeRepository.retrieveChallenge(id)
|
||||
.flatMap { challengeRepository.retrieveChallengeTasks(id) }
|
||||
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError(), Action { })
|
||||
}
|
||||
}
|
||||
|
||||
private fun set(challenge: Challenge) {
|
||||
challengeName?.text = EmojiParser.parseEmojis(challenge.name)
|
||||
challengeDescription?.text = MarkdownParser.parseMarkdown(challenge.description)
|
||||
challengeLeaderLabel?.username = challenge.leaderName
|
||||
|
||||
gemAmountView?.text = challenge.prize.toString()
|
||||
memberCountView?.text = challenge.memberCount.toString()
|
||||
}
|
||||
|
||||
private fun set(creator: Member) {
|
||||
challengeLeaderAvatarView?.setAvatar(creator)
|
||||
challengeLeaderLabel?.tier = creator.contributor?.level ?: 0
|
||||
challengeLeaderLabel?.username = creator.displayName
|
||||
}
|
||||
|
||||
private fun setJoined(joined: Boolean) {
|
||||
joinButton?.visibility = if (!joined) View.VISIBLE else View.GONE
|
||||
joinButtonWrapper?.visibility = if (!joined) View.VISIBLE else View.GONE
|
||||
leaveButton?.visibility = if (joined) View.VISIBLE else View.GONE
|
||||
leaveButonWrapper?.visibility = if (joined) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun addHabits(habits: ArrayList<Task>) {
|
||||
val taskGroup = taskGrouplayout?.inflate(R.layout.dialog_challenge_detail_task_group)
|
||||
val groupName = taskGroup?.findViewById(R.id.task_group_name) as TextView?
|
||||
val tasksLayout = taskGroup?.findViewById(R.id.tasks_layout) as LinearLayout?
|
||||
|
||||
groupName?.text = getLabelByTypeAndCount(Challenge.TASK_ORDER_HABITS, habits.size)
|
||||
taskGroup?.findViewById<TextView>(R.id.task_count_view)?.text = habits.size.toString()
|
||||
|
||||
val size = habits.size
|
||||
for (i in 0 until size) {
|
||||
val task = habits[i]
|
||||
val entry = tasksLayout?.inflate(R.layout.dialog_challenge_detail_habit)
|
||||
val habitTitle = entry?.findViewById(R.id.habit_title) as TextView?
|
||||
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon_plus)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#DFDEDF")))
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon_minus)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#DFDEDF")))
|
||||
context.notNull {
|
||||
if (task.up == true) {
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon_plus)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#B3FFFFFF")))
|
||||
entry?.findViewById<View>(R.id.lock_icon_background_plus)?.setBackgroundColor(ContextCompat.getColor(it, task.mediumTaskColor))
|
||||
val drawable = ContextCompat.getDrawable(it, R.drawable.circle_white)
|
||||
drawable?.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(it, task.darkTaskColor), PorterDuff.Mode.MULTIPLY)
|
||||
entry?.findViewById<View>(R.id.lock_icon_plus)?.setBackgroundDrawable(drawable)
|
||||
}
|
||||
if (task.down == true) {
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon_minus)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#B3FFFFFF")))
|
||||
entry?.findViewById<View>(R.id.lock_icon_background_minus)?.setBackgroundColor(ContextCompat.getColor(it, task.mediumTaskColor))
|
||||
val drawable = ContextCompat.getDrawable(it, R.drawable.circle_white)
|
||||
drawable?.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(it, task.darkTaskColor), PorterDuff.Mode.MULTIPLY)
|
||||
entry?.findViewById<View>(R.id.lock_icon_plus)?.setBackgroundDrawable(drawable)
|
||||
}
|
||||
}
|
||||
|
||||
habitTitle?.text = EmojiParser.parseEmojis(task.text)
|
||||
tasksLayout?.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addDailys(dailies: ArrayList<Task>) {
|
||||
val taskGroup = taskGrouplayout?.inflate(R.layout.dialog_challenge_detail_task_group)
|
||||
val groupName = taskGroup?.findViewById(R.id.task_group_name) as TextView?
|
||||
val tasksLayout = taskGroup?.findViewById(R.id.tasks_layout) as LinearLayout?
|
||||
|
||||
val size = dailies.size
|
||||
groupName?.text = getLabelByTypeAndCount(Challenge.TASK_ORDER_DAILYS, size)
|
||||
taskGroup?.findViewById<TextView>(R.id.task_count_view)?.text = dailies.size.toString()
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = dailies[i]
|
||||
val entry = tasksLayout?.inflate(R.layout.dialog_challenge_detail_daily)
|
||||
val title = entry?.findViewById(R.id.daily_title) as TextView?
|
||||
title?.text = EmojiParser.parseEmojis(task.text)
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#949494")))
|
||||
context.notNull {
|
||||
entry?.findViewById<View>(R.id.lock_icon_background)?.setBackgroundColor(ContextCompat.getColor(it, task.mediumTaskColor))
|
||||
val drawable = ContextCompat.getDrawable(it, R.drawable.circle_white)
|
||||
drawable?.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(it, task.extraLightTaskColor), PorterDuff.Mode.MULTIPLY)
|
||||
entry?.findViewById<View>(R.id.lock_icon)?.setBackgroundDrawable(drawable)
|
||||
}
|
||||
if (task.checklist != null && task.checklist?.isEmpty() == false) {
|
||||
val checklistIndicatorWrapper = entry?.findViewById<View>(R.id.checklistIndicatorWrapper)
|
||||
|
||||
checklistIndicatorWrapper?.visibility = View.VISIBLE
|
||||
|
||||
val checkListAllTextView = entry?.findViewById<View>(R.id.checkListAllTextView) as TextView?
|
||||
checkListAllTextView?.text = task.checklist?.size.toString()
|
||||
}
|
||||
tasksLayout?.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addTodos(todos: ArrayList<Task>) {
|
||||
val taskGroup = taskGrouplayout?.inflate(R.layout.dialog_challenge_detail_task_group)
|
||||
val groupName = taskGroup?.findViewById(R.id.task_group_name) as TextView?
|
||||
val tasksLayout = taskGroup?.findViewById(R.id.tasks_layout) as LinearLayout?
|
||||
|
||||
val size = todos.size
|
||||
groupName?.text = getLabelByTypeAndCount(Challenge.TASK_ORDER_TODOS, size)
|
||||
taskGroup?.findViewById<TextView>(R.id.task_count_view)?.text = todos.size.toString()
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = todos[i]
|
||||
val entry = tasksLayout?.inflate(R.layout.dialog_challenge_detail_todo)
|
||||
val title = entry?.findViewById(R.id.todo_title) as TextView?
|
||||
title?.text = EmojiParser.parseEmojis(task.text)
|
||||
entry?.findViewById<ImageView>(R.id.lock_icon)?.setImageBitmap(HabiticaIconsHelper.imageOfLocked(Color.parseColor("#949494")))
|
||||
context.notNull {
|
||||
entry?.findViewById<View>(R.id.lock_icon_background)?.setBackgroundColor(ContextCompat.getColor(it, task.mediumTaskColor))
|
||||
val drawable = ContextCompat.getDrawable(it, R.drawable.circle_white)
|
||||
drawable?.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(it, task.extraLightTaskColor), PorterDuff.Mode.MULTIPLY)
|
||||
entry?.findViewById<View>(R.id.lock_icon)?.setBackgroundDrawable(drawable)
|
||||
}
|
||||
|
||||
if (task.checklist != null && task.checklist?.isEmpty() == false) {
|
||||
val checklistIndicatorWrapper = entry?.findViewById<View>(R.id.checklistIndicatorWrapper)
|
||||
|
||||
checklistIndicatorWrapper?.visibility = View.VISIBLE
|
||||
|
||||
val checkListAllTextView = entry?.findViewById<View>(R.id.checkListAllTextView) as TextView?
|
||||
checkListAllTextView?.text = task.checklist?.size.toString()
|
||||
}
|
||||
tasksLayout?.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun addRewards(rewards: ArrayList<Task>) {
|
||||
val taskGroup = taskGrouplayout?.inflate(R.layout.dialog_challenge_detail_task_group)
|
||||
val groupName = taskGroup?.findViewById(R.id.task_group_name) as TextView?
|
||||
|
||||
val tasksLayout = taskGroup?.findViewById(R.id.tasks_layout) as LinearLayout?
|
||||
|
||||
val size = rewards.size
|
||||
groupName?.text = getLabelByTypeAndCount(Challenge.TASK_ORDER_REWARDS, size)
|
||||
taskGroup?.findViewById<TextView>(R.id.task_count_view)?.text = rewards.size.toString()
|
||||
|
||||
for (i in 0 until size) {
|
||||
val task = rewards[i]
|
||||
|
||||
val entry = tasksLayout?.inflate(R.layout.dialog_challenge_detail_reward)
|
||||
(entry?.findViewById<View>(R.id.gold_icon) as ImageView?)?.setImageBitmap(HabiticaIconsHelper.imageOfGold())
|
||||
val title = entry?.findViewById<View>(R.id.reward_title) as TextView?
|
||||
title?.text = EmojiParser.parseEmojis(task.text)
|
||||
tasksLayout?.addView(entry)
|
||||
}
|
||||
taskGrouplayout?.addView(taskGroup)
|
||||
}
|
||||
|
||||
private fun getLabelByTypeAndCount(type: String, count: Int): String {
|
||||
return when (type) {
|
||||
Challenge.TASK_ORDER_DAILYS -> context?.getString(if (count == 1) R.string.daily else R.string.dailies)
|
||||
Challenge.TASK_ORDER_HABITS -> context?.getString(if (count == 1) R.string.habit else R.string.habits)
|
||||
Challenge.TASK_ORDER_REWARDS -> context?.getString(if (count == 1) R.string.reward else R.string.rewards)
|
||||
else -> context?.getString(if (count == 1) R.string.todo else R.string.todos)
|
||||
} ?: ""
|
||||
}
|
||||
}
|
||||
|
|
@ -71,10 +71,10 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
|
|||
continue
|
||||
}
|
||||
val group = Group()
|
||||
group.id = challenge.groupId
|
||||
group.id = challenge.groupId ?: ""
|
||||
group.name = challenge.groupName
|
||||
|
||||
groupMap[challenge.groupName] = group
|
||||
groupMap[challenge.groupName ?: ""] = group
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,11 +92,11 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
|
|||
}
|
||||
|
||||
|
||||
fun allClicked() {
|
||||
private fun allClicked() {
|
||||
this.adapter?.selectAll()
|
||||
}
|
||||
|
||||
fun noneClicked() {
|
||||
private fun noneClicked() {
|
||||
this.adapter?.deSelectAll()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.extensions.inflate
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
|
|
@ -69,6 +70,8 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
|
|||
resetViews()
|
||||
|
||||
challengeAdapter = ChallengesListViewAdapter(null, true, viewUserChallengesOnly, userId)
|
||||
challengeAdapter?.getOpenDetailFragmentFlowable()?.subscribe(Consumer { openDetailFragment(it) }, RxErrorHandler.handleEmptyError())
|
||||
.notNull { compositeSubscription.add(it) }
|
||||
|
||||
swipeRefreshLayout?.setOnRefreshListener(this)
|
||||
|
||||
|
|
@ -81,9 +84,16 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
|
|||
recyclerView?.setEmptyView(emptyView)
|
||||
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
|
||||
challengeAdapter?.updateUnfilteredData(challenges)
|
||||
loadLocalChallenges()
|
||||
}
|
||||
|
||||
private fun openDetailFragment(challengeID: String) {
|
||||
val detailFragment = ChallengeDetailFragment()
|
||||
detailFragment.challengeID = challengeID
|
||||
this.activity?.displayFragment(detailFragment)
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
|
@ -93,32 +103,32 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
|
|||
}
|
||||
|
||||
private fun setRefreshing(state: Boolean) {
|
||||
if (swipeRefreshLayout != null && swipeRefreshLayout!!.visibility == View.VISIBLE) {
|
||||
swipeRefreshLayout!!.isRefreshing = state
|
||||
}
|
||||
swipeRefreshLayout?.isRefreshing = state
|
||||
}
|
||||
|
||||
private fun loadLocalChallenges() {
|
||||
val observable: Flowable<RealmResults<Challenge>> = if (viewUserChallengesOnly && user != null) {
|
||||
challengeRepository.getUserChallenges(user?.id)
|
||||
challengeRepository.getUserChallenges(user?.id ?: "")
|
||||
} else {
|
||||
challengeRepository.challenges
|
||||
challengeRepository.getChallenges()
|
||||
}
|
||||
|
||||
observable.firstElement().subscribe(Consumer { challenges ->
|
||||
compositeSubscription.add(observable.firstElement().subscribe(Consumer { challenges ->
|
||||
if (challenges.size == 0) {
|
||||
fetchOnlineChallenges()
|
||||
}
|
||||
this.challenges = challenges
|
||||
challengeAdapter!!.updateUnfilteredData(challenges)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
challengeAdapter?.updateUnfilteredData(challenges)
|
||||
}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
private fun fetchOnlineChallenges() {
|
||||
setRefreshing(true)
|
||||
challengeRepository.retrieveChallenges(user).doOnComplete {
|
||||
setRefreshing(false)
|
||||
} .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
user.notNull {
|
||||
challengeRepository.retrieveChallenges(it).doOnComplete {
|
||||
setRefreshing(false)
|
||||
} .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
override fun customTitle(): String {
|
||||
|
|
@ -141,13 +151,15 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
|
|||
}
|
||||
|
||||
private fun showFilterDialog() {
|
||||
ChallengeFilterDialogHolder.showDialog(getActivity()!!,
|
||||
challenges ?: emptyList(),
|
||||
filterOptions, object : Action1<ChallengeFilterOptions> {
|
||||
override fun call(t: ChallengeFilterOptions) {
|
||||
changeFilter(t)
|
||||
}
|
||||
})
|
||||
activity.notNull {
|
||||
ChallengeFilterDialogHolder.showDialog(it,
|
||||
challenges ?: emptyList(),
|
||||
filterOptions, object : Action1<ChallengeFilterOptions> {
|
||||
override fun call(t: ChallengeFilterOptions) {
|
||||
changeFilter(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeFilter(challengeFilterOptions: ChallengeFilterOptions) {
|
||||
|
|
@ -159,7 +171,7 @@ class ChallengeListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefreshLi
|
|||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
val id = item!!.itemId
|
||||
val id = item?.itemId
|
||||
|
||||
when (id) {
|
||||
R.id.action_create_challenge -> {
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges;
|
||||
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
public class ChallengeTasksRecyclerViewFragment extends BaseFragment {
|
||||
public RecyclerView recyclerView;
|
||||
public BaseTasksRecyclerViewAdapter recyclerAdapter;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userID;
|
||||
|
||||
List<Task> tasksOnInitialize;
|
||||
|
||||
LinearLayoutManager layoutManager = null;
|
||||
private User user;
|
||||
private View view;
|
||||
|
||||
public static ChallengeTasksRecyclerViewFragment newInstance(User user, List<Task> tasks) {
|
||||
ChallengeTasksRecyclerViewFragment fragment = new ChallengeTasksRecyclerViewFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.user = user;
|
||||
fragment.tasksOnInitialize = tasks;
|
||||
|
||||
if (tasks.size() != 0 && fragment.recyclerAdapter != null) {
|
||||
fragment.recyclerAdapter.setTasks(tasks);
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public void setInnerAdapter() {
|
||||
this.recyclerAdapter = new ChallengeTasksRecyclerViewAdapter(null, 0, getContext(), userID, null, true, true);
|
||||
|
||||
if (user != null && user.getPreferences() != null) {
|
||||
this.recyclerAdapter.setDailyResetOffset(user.getPreferences().getDayStart());
|
||||
}
|
||||
|
||||
if (tasksOnInitialize != null && tasksOnInitialize.size() != 0 && recyclerAdapter != null && recyclerAdapter.getItemCount() == 0) {
|
||||
recyclerAdapter.setTasks(tasksOnInitialize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
view = inflater.inflate(R.layout.fragment_recyclerview, container, false);
|
||||
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
|
||||
|
||||
android.support.v4.app.FragmentActivity context = getActivity();
|
||||
|
||||
layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
|
||||
if (layoutManager == null) {
|
||||
layoutManager = new LinearLayoutManager(context);
|
||||
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
}
|
||||
if (recyclerView.getAdapter() == null) {
|
||||
this.setInnerAdapter();
|
||||
}
|
||||
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
recyclerView.setAdapter(recyclerAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayedClassName() {
|
||||
return "ChallengeTasks" + super.getDisplayedClassName();
|
||||
}
|
||||
|
||||
|
||||
// region Challenge specific RecyclerViewAdapters
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.social.challenges
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
|
|
@ -12,17 +11,9 @@ import android.view.ViewGroup
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailActivityCommand
|
||||
import com.habitrpg.android.habitica.events.commands.ShowChallengeDetailDialogCommand
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import com.habitrpg.android.habitica.utils.Action1
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import com.habitrpg.android.habitica.ui.helpers.resetViews
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -33,30 +24,27 @@ class ChallengesOverviewFragment : BaseMainFragment() {
|
|||
|
||||
private val viewPager: ViewPager? by bindView(R.id.viewPager)
|
||||
var statePagerAdapter: FragmentStatePagerAdapter? = null
|
||||
private var userChallengesFragment: ChallengeListFragment? = null
|
||||
private var availableChallengesFragment: ChallengeListFragment? = null
|
||||
private var userChallengesFragment: ChallengeListFragment? = ChallengeListFragment()
|
||||
private var availableChallengesFragment: ChallengeListFragment? = ChallengeListFragment()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
this.usesTabLayout = true
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
val v = inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
|
||||
return v
|
||||
return inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setViewPagerAdapter()
|
||||
resetViews()
|
||||
|
||||
userChallengesFragment = ChallengeListFragment()
|
||||
userChallengesFragment?.user = this.user
|
||||
userChallengesFragment?.setViewUserChallengesOnly(true)
|
||||
|
||||
availableChallengesFragment = ChallengeListFragment()
|
||||
availableChallengesFragment?.user = this.user
|
||||
availableChallengesFragment?.setViewUserChallengesOnly(false)
|
||||
setViewPagerAdapter()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -98,28 +86,7 @@ class ChallengesOverviewFragment : BaseMainFragment() {
|
|||
}
|
||||
viewPager?.adapter = statePagerAdapter
|
||||
tabLayout?.setupWithViewPager(viewPager)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(cmd: ShowChallengeDetailDialogCommand) {
|
||||
challengeRepository.getChallenge(cmd.challengeId).firstElement().subscribe(Consumer { challenge ->
|
||||
ChallengeDetailDialogHolder.showDialog(activity, challengeRepository, challenge,
|
||||
object: Action1<Challenge> {
|
||||
override fun call(t: Challenge) {
|
||||
|
||||
}
|
||||
})
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(cmd: ShowChallengeDetailActivityCommand) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(ChallengeDetailActivity.CHALLENGE_ID, cmd.challengeId)
|
||||
|
||||
val intent = Intent(activity, ChallengeDetailActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
activity?.startActivity(intent)
|
||||
statePagerAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun customTitle(): String {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class CollapsibleSectionView(context: Context?, attrs: AttributeSet?) : LinearLa
|
|||
private val titleView: LinearLayout by bindView(R.id.title_view)
|
||||
private val titleLabel: TextView by bindView(R.id.titleTextView)
|
||||
private val caretView: ImageView by bindView(R.id.caretView)
|
||||
public val infoIconView: ImageView by bindView(R.id.infoIconView)
|
||||
val infoIconView: ImageView by bindView(R.id.infoIconView)
|
||||
private var preferences: SharedPreferences? = null
|
||||
private val padding = context?.resources?.getDimension(R.dimen.spacing_large)?.toInt() ?: 0
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ class CollapsibleSectionView(context: Context?, attrs: AttributeSet?) : LinearLa
|
|||
titleLabel.text = value
|
||||
}
|
||||
|
||||
var isCollapsed = false
|
||||
private var isCollapsed = false
|
||||
set(value) {
|
||||
field = value
|
||||
if (value) {
|
||||
|
|
@ -128,7 +128,7 @@ class CollapsibleSectionView(context: Context?, attrs: AttributeSet?) : LinearLa
|
|||
}
|
||||
|
||||
if (attributes?.getBoolean(R.styleable.CollapsibleSectionView_hasAdditionalInfo, false) == true) {
|
||||
infoIconView.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon())
|
||||
infoIconView.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon(ContextCompat.getColor(context, R.color.brand_200)))
|
||||
} else {
|
||||
infoIconView.visibility = View.GONE
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -3,8 +3,11 @@ package com.habitrpg.android.habitica.ui.views;
|
|||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.ColorRes;
|
||||
|
||||
/**
|
||||
* Created by phillip on 05.09.17.
|
||||
|
|
@ -262,7 +265,7 @@ public class HabiticaIconsHelper {
|
|||
imageOfItemIndicatorNumber = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfItemIndicatorNumber);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawItemIndicator(canvas, false, false);
|
||||
HabiticaIcons.drawItemIndicator(canvas, Color.parseColor("#C3C0C7"), false, false);
|
||||
|
||||
return imageOfItemIndicatorNumber;
|
||||
}
|
||||
|
|
@ -276,8 +279,7 @@ public class HabiticaIconsHelper {
|
|||
imageOfItemIndicatorLocked = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfItemIndicatorLocked);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawItemIndicator(canvas, true, false);
|
||||
|
||||
HabiticaIcons.drawItemIndicator(canvas, Color.parseColor("#C3C0C7"), true, false);
|
||||
return imageOfItemIndicatorLocked;
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +292,7 @@ public class HabiticaIconsHelper {
|
|||
imageOfItemIndicatorLimited = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfItemIndicatorLimited);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawItemIndicator(canvas, false, true);
|
||||
HabiticaIcons.drawItemIndicator(canvas, Color.parseColor("#C3C0C7"), false, true);
|
||||
|
||||
return imageOfItemIndicatorLimited;
|
||||
}
|
||||
|
|
@ -474,7 +476,7 @@ public class HabiticaIconsHelper {
|
|||
}
|
||||
|
||||
private static Bitmap imageOfInfoIcon = null;
|
||||
public static Bitmap imageOfInfoIcon() {
|
||||
public static Bitmap imageOfInfoIcon(@ColorInt int iconColor) {
|
||||
if (imageOfInfoIcon != null)
|
||||
return imageOfInfoIcon;
|
||||
|
||||
|
|
@ -482,7 +484,7 @@ public class HabiticaIconsHelper {
|
|||
imageOfInfoIcon = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfInfoIcon);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawInfoIcon(canvas);
|
||||
HabiticaIcons.drawInfoIcon(canvas, iconColor);
|
||||
|
||||
return imageOfInfoIcon;
|
||||
}
|
||||
|
|
@ -576,4 +578,27 @@ public class HabiticaIconsHelper {
|
|||
|
||||
return imageOfRage;
|
||||
}
|
||||
|
||||
public static Bitmap imageOfLocked(@ColorInt int lockColor) {
|
||||
Bitmap imageOfLocked = Bitmap.createBitmap(scaleSize(15), scaleSize(17), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfLocked);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawLocked(canvas, lockColor);
|
||||
|
||||
return imageOfLocked;
|
||||
}
|
||||
|
||||
private static Bitmap imageOfParticipantsIcon = null;
|
||||
public static Bitmap imageOfParticipantIcon() {
|
||||
if (imageOfParticipantsIcon != null)
|
||||
return imageOfParticipantsIcon;
|
||||
|
||||
int size = scaleSize(20);
|
||||
imageOfParticipantsIcon = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imageOfParticipantsIcon);
|
||||
canvas.scale(displayDensity, displayDensity);
|
||||
HabiticaIcons.drawParticipantsIcon(canvas);
|
||||
|
||||
return imageOfParticipantsIcon;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
package com.habitrpg.android.habitica.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
|
||||
public class ChallengeDeserializer implements JsonDeserializer<Challenge>, JsonSerializer<Challenge> {
|
||||
@Override
|
||||
public Challenge deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
|
||||
JsonObject jsonObject = json.getAsJsonObject();
|
||||
|
||||
Challenge challenge = new Challenge();
|
||||
|
||||
challenge.id = jsonObject.get("id").getAsString();
|
||||
challenge.name = jsonObject.get("name").getAsString();
|
||||
if (jsonObject.has("sortName")) {
|
||||
challenge.shortName = jsonObject.get("shortName").getAsString();
|
||||
}
|
||||
challenge.description = jsonObject.get("description").getAsString();
|
||||
challenge.memberCount = jsonObject.get("memberCount").getAsInt();
|
||||
|
||||
JsonElement prizeElement = jsonObject.get("prize");
|
||||
if (!prizeElement.isJsonNull()) {
|
||||
challenge.prize = prizeElement.getAsInt();
|
||||
}
|
||||
|
||||
challenge.official = jsonObject.get("official").getAsBoolean();
|
||||
|
||||
JsonElement leaderElement = jsonObject.get("leader");
|
||||
|
||||
if (leaderElement != null && !leaderElement.isJsonNull()) {
|
||||
JsonObject leaderObj = leaderElement.getAsJsonObject();
|
||||
|
||||
if (leaderObj != null) {
|
||||
JsonObject profile = leaderObj.get("profile").getAsJsonObject();
|
||||
|
||||
if (profile != null) {
|
||||
challenge.leaderName = profile.get("name").getAsString();
|
||||
|
||||
JsonElement id = leaderObj.get("id");
|
||||
if (id == null) {
|
||||
id = leaderObj.get("_id");
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
challenge.leaderId = id.getAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonObject.has("createdAt")) {
|
||||
challenge.createdAt = context.deserialize(jsonObject.get("createdAt"), Date.class);
|
||||
}
|
||||
if (jsonObject.has("updatedAt")) {
|
||||
challenge.updatedAt = context.deserialize(jsonObject.get("updatedAt"), Date.class);
|
||||
}
|
||||
|
||||
JsonElement groupElement = jsonObject.get("group");
|
||||
|
||||
if (groupElement != null && !groupElement.isJsonNull()) {
|
||||
JsonObject groupObj = groupElement.getAsJsonObject();
|
||||
|
||||
if (groupObj != null) {
|
||||
challenge.groupName = groupObj.get("name").getAsString();
|
||||
challenge.groupId = groupObj.get("_id").getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
JsonElement tasksOrderElement = jsonObject.get("tasksOrder");
|
||||
|
||||
if (tasksOrderElement != null && !tasksOrderElement.isJsonNull()) {
|
||||
JsonObject tasksOrderObj = tasksOrderElement.getAsJsonObject();
|
||||
|
||||
challenge.todoList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_TODOS);
|
||||
challenge.dailyList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_DAILYS);
|
||||
challenge.habitList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_HABITS);
|
||||
challenge.rewardList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_REWARDS);
|
||||
}
|
||||
|
||||
return challenge;
|
||||
}
|
||||
|
||||
private String getTaskArrayAsString(JsonDeserializationContext context, JsonObject tasksOrderObj, String taskType) {
|
||||
|
||||
if (tasksOrderObj.has(taskType)) {
|
||||
JsonElement jsonElement = tasksOrderObj.get(taskType);
|
||||
|
||||
String[] taskArray = context.deserialize(jsonElement, String[].class);
|
||||
|
||||
return TextUtils.join(",", taskArray);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Challenge src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonObject object = new JsonObject();
|
||||
object.addProperty("id", src.id);
|
||||
object.addProperty("name", src.name);
|
||||
object.addProperty("shortName", src.shortName);
|
||||
object.addProperty("description", src.description);
|
||||
object.addProperty("memberCount", src.memberCount);
|
||||
object.addProperty("prize", src.prize);
|
||||
object.addProperty("official", src.official);
|
||||
|
||||
object.addProperty("group", src.groupId);
|
||||
object.add("tasksOrder", context.serialize(src.tasksOrder));
|
||||
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
package com.habitrpg.android.habitica.utils
|
||||
|
||||
import android.text.TextUtils
|
||||
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
|
||||
import java.lang.reflect.Type
|
||||
import java.util.Date
|
||||
|
||||
class ChallengeDeserializer : JsonDeserializer<Challenge>, JsonSerializer<Challenge> {
|
||||
@Throws(JsonParseException::class)
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Challenge {
|
||||
|
||||
val jsonObject = json.asJsonObject
|
||||
|
||||
val challenge = Challenge()
|
||||
|
||||
challenge.id = jsonObject.get("id").asString
|
||||
challenge.name = jsonObject.get("name").asString
|
||||
if (jsonObject.has("sortName")) {
|
||||
challenge.shortName = jsonObject.get("shortName").asString
|
||||
}
|
||||
challenge.description = jsonObject.get("description").asString
|
||||
challenge.memberCount = jsonObject.get("memberCount").asInt
|
||||
|
||||
val prizeElement = jsonObject.get("prize")
|
||||
if (!prizeElement.isJsonNull) {
|
||||
challenge.prize = prizeElement.asInt
|
||||
}
|
||||
|
||||
challenge.official = jsonObject.get("official").asBoolean
|
||||
|
||||
val leaderElement = jsonObject.get("leader")
|
||||
|
||||
if (leaderElement != null && !leaderElement.isJsonNull) {
|
||||
val leaderObj = leaderElement.asJsonObject
|
||||
|
||||
if (leaderObj != null) {
|
||||
val profile = leaderObj.get("profile").asJsonObject
|
||||
|
||||
if (profile != null) {
|
||||
challenge.leaderName = profile.get("name").asString
|
||||
|
||||
var id: JsonElement? = leaderObj.get("id")
|
||||
if (id == null) {
|
||||
id = leaderObj.get("_id")
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
challenge.leaderId = id.asString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonObject.has("createdAt")) {
|
||||
challenge.createdAt = context.deserialize(jsonObject.get("createdAt"), Date::class.java)
|
||||
}
|
||||
if (jsonObject.has("updatedAt")) {
|
||||
challenge.updatedAt = context.deserialize(jsonObject.get("updatedAt"), Date::class.java)
|
||||
}
|
||||
|
||||
val groupElement = jsonObject.get("group")
|
||||
|
||||
if (groupElement != null && !groupElement.isJsonNull) {
|
||||
val groupObj = groupElement.asJsonObject
|
||||
|
||||
if (groupObj != null) {
|
||||
challenge.groupName = groupObj.get("name").asString
|
||||
challenge.groupId = groupObj.get("_id").asString
|
||||
}
|
||||
}
|
||||
|
||||
val tasksOrderElement = jsonObject.get("tasksOrder")
|
||||
|
||||
if (tasksOrderElement != null && !tasksOrderElement.isJsonNull) {
|
||||
val tasksOrderObj = tasksOrderElement.asJsonObject
|
||||
|
||||
challenge.todoList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_TODOS)
|
||||
challenge.dailyList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_DAILYS)
|
||||
challenge.habitList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_HABITS)
|
||||
challenge.rewardList = getTaskArrayAsString(context, tasksOrderObj, Challenge.TASK_ORDER_REWARDS)
|
||||
}
|
||||
|
||||
return challenge
|
||||
}
|
||||
|
||||
private fun getTaskArrayAsString(context: JsonDeserializationContext, tasksOrderObj: JsonObject, taskType: String): String {
|
||||
|
||||
if (tasksOrderObj.has(taskType)) {
|
||||
val jsonElement = tasksOrderObj.get(taskType)
|
||||
|
||||
val taskArray = context.deserialize<Array<String>>(jsonElement, Array<String>::class.java)
|
||||
|
||||
return TextUtils.join(",", taskArray)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun serialize(src: Challenge, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
val obj = JsonObject()
|
||||
obj.addProperty("id", src.id)
|
||||
obj.addProperty("name", src.name)
|
||||
obj.addProperty("shortName", src.shortName)
|
||||
obj.addProperty("description", src.description)
|
||||
obj.addProperty("memberCount", src.memberCount)
|
||||
obj.addProperty("prize", src.prize)
|
||||
obj.addProperty("official", src.official)
|
||||
|
||||
obj.addProperty("group", src.groupId)
|
||||
obj.add("tasksOrder", context.serialize(src.tasksOrder))
|
||||
|
||||
|
||||
return obj
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package com.habitrpg.android.habitica.utils;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import io.realm.Realm;
|
||||
import io.realm.RealmList;
|
||||
|
||||
public class ChallengeListDeserializer implements JsonDeserializer<List<Challenge>> {
|
||||
@Override
|
||||
public List<Challenge> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
RealmList<Challenge> challenges = new RealmList<>();
|
||||
|
||||
Realm realm = Realm.getDefaultInstance();
|
||||
List<Challenge> existingChallenges = realm.copyFromRealm(realm.where(Challenge.class).findAll());
|
||||
realm.close();
|
||||
|
||||
for (JsonElement element : json.getAsJsonArray()) {
|
||||
Challenge challenge;
|
||||
if (element.isJsonObject()) {
|
||||
challenge = context.deserialize(element, Challenge.class);
|
||||
Challenge existingChallenge = findExistingChallenge(existingChallenges, challenge.id);
|
||||
if (existingChallenge != null) {
|
||||
challenge.isParticipating = existingChallenge.isParticipating;
|
||||
}
|
||||
} else {
|
||||
challenge = findExistingChallenge(existingChallenges, element.getAsString());
|
||||
if (challenge == null) {
|
||||
challenge = new Challenge();
|
||||
challenge.id = element.getAsString();
|
||||
}
|
||||
challenge.isParticipating = true;
|
||||
}
|
||||
challenges.add(challenge);
|
||||
}
|
||||
|
||||
return challenges;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Challenge findExistingChallenge(List<Challenge> existingChallenges, String id) {
|
||||
for (Challenge challenge : existingChallenges) {
|
||||
if (id.equals(challenge.id)) {
|
||||
return challenge;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.habitrpg.android.habitica.utils
|
||||
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonParseException
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
|
||||
import java.lang.reflect.Type
|
||||
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmList
|
||||
|
||||
class ChallengeListDeserializer : JsonDeserializer<List<Challenge>> {
|
||||
@Throws(JsonParseException::class)
|
||||
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): List<Challenge> {
|
||||
val challenges = RealmList<Challenge>()
|
||||
|
||||
val realm = Realm.getDefaultInstance()
|
||||
realm.close()
|
||||
|
||||
for (element in json.asJsonArray) {
|
||||
var challenge: Challenge?
|
||||
if (element.isJsonObject) {
|
||||
challenge = context.deserialize<Challenge>(element, Challenge::class.java)
|
||||
} else {
|
||||
challenge = Challenge()
|
||||
challenge.id = element.asString
|
||||
}
|
||||
if (challenge != null) {
|
||||
challenges.add(challenge)
|
||||
}
|
||||
}
|
||||
|
||||
return challenges
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import com.habitrpg.android.habitica.models.PushDevice
|
|||
import com.habitrpg.android.habitica.models.Tag
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
import com.habitrpg.android.habitica.models.invitations.Invitations
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.social.UserParty
|
||||
import com.habitrpg.android.habitica.models.tasks.TasksOrder
|
||||
import com.habitrpg.android.habitica.models.user.*
|
||||
|
|
@ -84,7 +84,10 @@ class UserDeserializer : JsonDeserializer<User> {
|
|||
user.tasksOrder = context.deserialize(obj.get("tasksOrder"), TasksOrder::class.java)
|
||||
}
|
||||
if (obj.has("challenges")) {
|
||||
user.challenges = context.deserialize(obj.get("challenges"), object : TypeToken<RealmList<Challenge>>() {}.type)
|
||||
user.challenges = RealmList()
|
||||
obj.getAsJsonArray("challenges").forEach {
|
||||
user.challenges.add(ChallengeMembership(user.id, it.asString))
|
||||
}
|
||||
}
|
||||
if (obj.has("purchased")) {
|
||||
user.purchased = context.deserialize(obj.get("purchased"), Purchases::class.java)
|
||||
|
|
|
|||
Loading…
Reference in a new issue