mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-21 05:15:00 +00:00
Improve group plans support
This commit is contained in:
parent
472a35281f
commit
5049c622dd
115 changed files with 1115 additions and 432 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
android:shape="rectangle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
<corners android:radius="6dp" />
|
||||
</shape>
|
||||
<ripple android:color="@color/white" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<size android:width="24dp" android:height="80dp" />
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:topRightRadius="8dp" android:bottomRightRadius="8dp" />
|
||||
</shape>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
|
||||
<stroke
|
||||
android:width="0.5dip"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:topLeftRadius="@dimen/bottom_sheet_radius" android:topRightRadius="@dimen/bottom_sheet_radius" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:topLeftRadius="@dimen/bottom_sheet_radius" android:topRightRadius="@dimen/bottom_sheet_radius" />
|
||||
</shape>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/rounded_button_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -6,6 +6,6 @@
|
|||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:pathData="M0,12l0,12 11.5,-5.7c6.3,-3.2 11.5,-6 11.5,-6.3 0,-0.3 -5.2,-3.1 -11.5,-6.3l-11.5,-5.7 0,12z"
|
||||
android:strokeColor="@color/content_background"
|
||||
android:fillColor="@color/content_background"/>
|
||||
android:strokeColor="?attr/colorContentBackground"
|
||||
android:fillColor="?attr/colorContentBackground"/>
|
||||
</vector>
|
||||
10
Habitica/res/drawable/edit.xml
Normal file
10
Habitica/res/drawable/edit.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16.188,7.542 L12.458,3.812 13.479,2.792Q14,2.271 14.719,2.271Q15.438,2.271 15.958,2.792L17.208,4.042Q17.708,4.542 17.708,5.281Q17.708,6.021 17.208,6.521ZM14.958,8.771 L6.229,17.5H2.5V13.771L11.229,5.042Z"/>
|
||||
</vector>
|
||||
|
|
@ -3,6 +3,6 @@
|
|||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="@color/content_80_alpha"
|
||||
android:startColor="@color/content_background"
|
||||
android:startColor="?attr/colorContentBackground"
|
||||
android:type="linear" />
|
||||
</shape>
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<size android:width="24dp" android:height="24dp" />
|
||||
<stroke android:color="@color/content_background_offset" android:width="2dp" />
|
||||
<stroke android:color="?attr/colorContentBackgroundOffset" android:width="2dp" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
<corners android:radius="@dimen/rounded_button_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/content_background_offset" />
|
||||
<solid android:color="?attr/colorContentBackgroundOffset" />
|
||||
<corners android:radius="@dimen/bar_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="6dp"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
<corners android:radius="@dimen/rounded_button_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/rounded_button_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/bar_radius"/>
|
||||
<stroke android:width="2dp" android:color="@color/blue_10" />
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/bar_radius"/>
|
||||
<stroke android:width="2dp" android:color="@color/background_brand" />
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/bar_radius"/>
|
||||
<stroke android:width="2dp" android:color="@color/red_10" />
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/rounded_button_radius"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
<stroke android:color="?colorAccent" android:width="2dp" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="@dimen/bar_radius"/>
|
||||
<stroke android:width="2dp" android:color="@color/yellow_5" />
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<gradient
|
||||
android:angle="90"
|
||||
android:centerColor="@color/transparent_white"
|
||||
android:endColor="@color/content_background"
|
||||
android:startColor="@color/content_background"
|
||||
android:endColor="?attr/colorContentBackground"
|
||||
android:startColor="?attr/colorContentBackground"
|
||||
android:type="linear"
|
||||
android:centerX="0.6"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M0,15v-3l0.7,-0.34 1.05,-0.49 0.95,-0.43 0.84,-0.36 1.27,-0.54 1.07,-0.44 1.57,-0.63 1.28,-0.5 1.37,-0.51 0.96,-0.35 0.99,-0.35 1.03,-0.36 1.06,-0.36L15.25,6l1.7,-0.54 1.17,-0.36 1.2,-0.35 0.61,-0.18 1.24,-0.35 0.63,-0.17 1.28,-0.34c0.43,-0.11 0.87,-0.22 1.3,-0.33l1.33,-0.32a124.57,124.57 0,0 1,4.81 -1.05l1.42,-0.27C37.64,0.69 43.76,0 50,0c4.42,0 9.12,0.33 14.19,0.89l1.8,0.2 1.84,0.22 0.93,0.12 1.88,0.25 1.92,0.26 1.95,0.27 1.99,0.29 3.05,0.45 5.26,0.8 6.63,1.02 4.63,0.7 3.58,0.53 2.44,0.35 2.49,0.35 2.53,0.35 2.58,0.35 1.31,0.17 2.65,0.34c0.89,0.11 1.79,0.22 2.7,0.33l2.74,0.33 2.09,0.24 2.12,0.23 2.15,0.23 1.09,0.11 2.19,0.22 2.22,0.21 2.25,0.21 2.28,0.2 2.31,0.19c0.39,0.03 0.78,0.06 1.17,0.09l2.36,0.18 2.39,0.17 1.21,0.08 2.44,0.15 2.47,0.14 1.25,0.07 2.52,0.13 2.55,0.12c0.43,0.02 0.86,0.04 1.29,0.05l2.6,0.1 2.63,0.09 1.33,0.04 2.69,0.07c1.8,0.04 3.63,0.07 5.48,0.09l2.03,0.02h7.81c12.46,-0.09 24.81,-0.58 36.7,-1.3l3.39,-0.21 1.68,-0.11 3.35,-0.23 3.32,-0.24 1.65,-0.12 3.27,-0.25 4.04,-0.33 5.57,-0.48 3.13,-0.28 4.62,-0.43 4.52,-0.44 2.96,-0.29 4.35,-0.44 4.24,-0.44 5.46,-0.58 17.28,-1.87 3.29,-0.35 3.13,-0.32 2,-0.2 1.92,-0.19 1.84,-0.17 1.77,-0.16 2.09,-0.17 1.97,-0.14 1.48,-0.09c0.64,-0.04 1.25,-0.07 1.84,-0.1l1.14,-0.04 1.07,-0.03A57.3,57.3 0,0 1,316 2c7.31,0 12.87,1.52 16.94,3.38l0.61,0.29 0.59,0.29c0.19,0.1 0.38,0.2 0.57,0.29l0.54,0.3 0.52,0.3 0.5,0.3 0.71,0.45 0.44,0.3 0.42,0.29 0.4,0.29 0.38,0.28 0.53,0.42 0.33,0.27 0.3,0.26 0.28,0.25 0.26,0.24 0.24,0.23 0.33,0.32 0.37,0.38 0.29,0.32 0.33,0.39 0.11,0.14v3.68L174.15,15H0z"
|
||||
android:fillColor="@color/content_background"
|
||||
android:fillColor="?attr/colorContentBackground"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background"/>
|
||||
<solid android:color="?attr/colorWindowBackground"/>
|
||||
<corners android:radius="20dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/content_background"/>
|
||||
<solid android:color="?attr/colorContentBackground"/>
|
||||
<corners android:radius="20dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background"/>
|
||||
<solid android:color="?attr/colorWindowBackground"/>
|
||||
<corners android:radius="20dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp" />
|
||||
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/offset_background"/>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
<size
|
||||
android:width="10dp"
|
||||
android:height="10dp" />
|
||||
<solid android:color="@color/content_background" />
|
||||
<solid android:color="?attr/colorContentBackground" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/content_background_offset" />
|
||||
android:color="?attr/colorContentBackgroundOffset" />
|
||||
</shape>
|
||||
</rotate>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background"/>
|
||||
<solid android:color="?attr/colorWindowBackground"/>
|
||||
<corners android:radius="8dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background"/>
|
||||
<solid android:color="?attr/colorWindowBackground"/>
|
||||
<corners android:radius="8dip"/>
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
<stroke android:color="@color/text_brand_neon" android:width="3dp" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<stroke android:color="@color/content_background_offset" android:width="1dp" />
|
||||
<stroke android:color="?attr/colorContentBackgroundOffset" android:width="1dp" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/window_background" />
|
||||
<solid android:color="?attr/colorWindowBackground" />
|
||||
<corners android:radius="20dp" />
|
||||
<stroke android:color="?colorAccent" android:width="2dp" />
|
||||
</shape>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.habitrpg.android.habitica.ui.activities.MainActivity"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/window_background"/>
|
||||
android:background="?attr/colorWindowBackground"/>
|
||||
<include layout="@layout/activity_main_content" android:id="@+id/content" />
|
||||
</LinearLayout>
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
<FrameLayout
|
||||
android:id="@+id/confetti_anchor"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="@style/Toolbar"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:title="@string/choose_class"
|
||||
app:titleTextColor="@color/text_primary"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -221,7 +221,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
android:id="@+id/create_challenge_task_list">
|
||||
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
<FrameLayout
|
||||
android:id="@+id/confetti_container"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/outer_inset"
|
||||
android:text="@string/fix_character_description"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:layout_marginBottom="16dp"
|
||||
/>
|
||||
<FrameLayout
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
<FrameLayout
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
<FrameLayout
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
<FrameLayout
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
<FrameLayout
|
||||
|
|
@ -241,7 +241,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
<FrameLayout
|
||||
|
|
@ -284,7 +284,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".ui.activities.PrefsActivity"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -78,6 +78,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/content_background" />
|
||||
android:background="?attr/colorContentBackground" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.habitrpg.android.habitica.ui.activities.MainActivity"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<!-- As the main content view, the view below consumes the entire
|
||||
space available using match_parent in both dimensions. -->
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".ui.activities.PrefsActivity"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:elevation="0dp"
|
||||
android:fillViewport="false"
|
||||
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/content_background" />
|
||||
android:background="?attr/colorContentBackground" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="@style/Toolbar"
|
||||
app:title=""
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:titleTextColor="@color/text_primary"
|
||||
app:theme="@style/ReportMessageToolbar"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/content_background" />
|
||||
android:background="?attr/colorContentBackground" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/colorTintedBackground"
|
||||
tools:context="com.habitrpg.android.habitica.ui.activities.FixCharacterValuesActivity">
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -29,7 +30,6 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorTintedBackground"
|
||||
android:paddingBottom="@dimen/spacing_large">
|
||||
<LinearLayout
|
||||
android:id="@+id/upper_text_wrapper"
|
||||
|
|
@ -126,10 +126,20 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/difficulty"
|
||||
style="@style/TaskFormSectionheader"/>
|
||||
<com.habitrpg.android.habitica.ui.views.tasks.form.TaskDifficultyButtons
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/task_difficulty_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/assign_title_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assign"
|
||||
style="@style/TaskFormSectionheader" />
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/assign_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/habit_reset_streak_title_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
android:paddingStart="@dimen/spacing_medium"
|
||||
android:paddingEnd="@dimen/spacing_medium"
|
||||
android:layout_marginStart="1dp"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:gravity="center_vertical"
|
||||
/>
|
||||
<View android:background="@color/gray_600"
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView android:text="@string/username"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:layout_height="41dp"
|
||||
android:paddingStart="@dimen/spacing_medium"
|
||||
android:paddingEnd="@dimen/spacing_medium"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/header_bar_spacing"
|
||||
app:barForegroundColor="@color/background_red"
|
||||
app:barBackgroundColor="@color/window_background"
|
||||
app:barBackgroundColor="?attr/colorWindowBackground"
|
||||
app:description="@string/HP_default"/>
|
||||
|
||||
<com.habitrpg.common.habitica.views.ValueBar
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/header_bar_spacing"
|
||||
app:barForegroundColor="@color/background_yellow"
|
||||
app:barBackgroundColor="@color/window_background"
|
||||
app:barBackgroundColor="?attr/colorWindowBackground"
|
||||
app:description="@string/XP_default"/>
|
||||
|
||||
<com.habitrpg.common.habitica.views.ValueBar
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:barForegroundColor="@color/background_blue"
|
||||
app:barBackgroundColor="@color/window_background"
|
||||
app:barBackgroundColor="?attr/colorWindowBackground"
|
||||
app:description="@string/MP_default"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="horizontal"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
android:paddingStart="@dimen/chat_horizontal_inset"
|
||||
android:paddingEnd="@dimen/chat_horizontal_inset"
|
||||
android:paddingTop="@dimen/spacing_small"
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/close"
|
||||
android:background="@drawable/alert_dialog_background"
|
||||
android:backgroundTint="@color/content_background"
|
||||
android:backgroundTint="?attr/colorContentBackground"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
app:shimmer_repeat_delay="4000"
|
||||
app:shimmer_duration="200"
|
||||
app:shimmer_base_color="@color/text_dimmed"
|
||||
app:shimmer_highlight_color="@color/content_background"
|
||||
app:shimmer_highlight_color="?attr/colorContentBackground"
|
||||
app:shimmer_highlight_alpha="0.4">
|
||||
<com.habitrpg.common.habitica.views.PixelArtView
|
||||
android:id="@+id/pet_view"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:gravity="center_vertical">
|
||||
<LinearLayout
|
||||
android:id="@+id/pin_button"
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:background="@color/content_background"/>
|
||||
android:background="?attr/colorContentBackground"/>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/content_background_offset"
|
||||
android:background="?attr/colorContentBackgroundOffset"
|
||||
android:layout_marginEnd="56dp"/>
|
||||
</merge>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
android:paddingEnd="32dp"
|
||||
android:paddingBottom="32dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:layout_marginTop="@dimen/spacing_large"
|
||||
android:gravity="center">
|
||||
<TextView
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/refreshLayout"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
style="@style/FragmentDialogTitle"
|
||||
android:id="@+id/titleTextView"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:textColor="@color/text_primary" />
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/refreshLayout"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
style="@style/FragmentDialogTitle"
|
||||
android:id="@+id/titleTextView"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:textColor="@color/text_primary" />
|
||||
<com.habitrpg.android.habitica.ui.helpers.RecyclerViewEmptySupport
|
||||
android:id="@+id/recyclerView"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
android:layout_height="63dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:padding="6dp"
|
||||
android:background="@color/window_background"/>
|
||||
android:background="?attr/colorWindowBackground"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/content_border"
|
||||
android:paddingEnd="@dimen/content_border"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:orientation="vertical">
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/window_background">
|
||||
android:background="?attr/colorWindowBackground">
|
||||
<TextView android:id="@+id/supportTextView"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<LinearLayout
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
android:layout_marginBottom="@dimen/spacing_large">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
android:paddingTop="@dimen/spacing_large"
|
||||
android:paddingBottom="@dimen/spacing_large">
|
||||
<LinearLayout
|
||||
|
|
@ -166,7 +166,7 @@
|
|||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/content_background_offset"/>
|
||||
android:background="?attr/colorContentBackgroundOffset"/>
|
||||
<Button
|
||||
android:id="@+id/reset_tutorial_button"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/window_background"
|
||||
android:background="?attr/colorWindowBackground"
|
||||
android:paddingTop="@dimen/spacing_large"
|
||||
android:paddingBottom="@dimen/spacing_large"
|
||||
android:paddingStart="@dimen/spacing_large"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
android:id="@+id/notification_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/content_background"
|
||||
android:background="?attr/colorContentBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="10dp"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:parentTag="android.widget.RelativeLayout"
|
||||
android:background="@color/window_background">
|
||||
android:background="?attr/colorWindowBackground">
|
||||
<LinearLayout
|
||||
android:id="@+id/contentWrapper"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:parentTag="android.widget.RelativeLayout"
|
||||
android:background="@color/window_background">
|
||||
android:background="?attr/colorWindowBackground">
|
||||
<LinearLayout
|
||||
android:id="@+id/contentWrapper"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:title="@string/world_boss_description"
|
||||
app:identifier="questDescription"
|
||||
app:color="@color/content_background">
|
||||
app:color="?attr/colorContentBackground">
|
||||
<TextView
|
||||
android:id="@+id/questDescription"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
android:gravity="center_horizontal"
|
||||
android:textColor="@color/text_secondary"
|
||||
style="@style/Body1"
|
||||
app:backgroundTint="@color/content_background_offset"
|
||||
app:backgroundTint="?attr/colorContentBackgroundOffset"
|
||||
android:textSize="16sp"
|
||||
android:inputType="number"/>
|
||||
</merge>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:background="@color/content_background">
|
||||
tools:background="?attr/colorContentBackground">
|
||||
<ImageView
|
||||
android:id="@+id/heart_icon"
|
||||
android:layout_width="20dp"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/checkbox_background"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/content_background">
|
||||
android:background="?attr/colorContentBackground">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/checkbox_background"
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,9 @@
|
|||
<string name="positive_and_negative">positive and negative</string>
|
||||
<string name="assigned_to">Assigned to</string>
|
||||
<string name="completed_at">Completed at %s</string>
|
||||
<string name="assign">Assign</string>
|
||||
<string name="edit_assignees">Edit assignees</string>
|
||||
<string name="assign_to">Assign to...</string>
|
||||
<plurals name="you_x_others">
|
||||
<item quantity="zero">You</item>
|
||||
<item quantity="one">You, %d other</item>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<item name="android:listSeparatorTextViewStyle">@style/MyOwnListSeperatorTextViewStyle</item>
|
||||
|
||||
<item name="android:elevation" tools:targetApi="21">0dp</item>
|
||||
<item name="android:elevation">0dp</item>
|
||||
<item name="elevation">0dp</item>
|
||||
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
<item name="barColor">@color/brand_300</item>
|
||||
|
||||
<item name="colorContentBackground">@color/content_background</item>
|
||||
<item name="colorContentBackgroundOffset">@color/content_background_offset</item>
|
||||
<item name="colorWindowBackground">@color/window_background</item>
|
||||
<item name="colorTintedBackground">@color/brand_800</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/brand_700</item>
|
||||
|
|
@ -55,8 +56,8 @@
|
|||
<item name="toolbarContentColor">@color/text_primary</item>
|
||||
<item name="colorPrimaryText">@color/brand_50</item>
|
||||
<item name="colorBoxStroke">@color/brand_50</item>
|
||||
<item name="headerBackgroundColor">@color/content_background</item>
|
||||
<item name="headerOffsetColor">@color/window_background</item>
|
||||
<item name="headerBackgroundColor">?attr/colorContentBackground</item>
|
||||
<item name="headerOffsetColor">?attr/colorWindowBackground</item>
|
||||
<item name="headerTextColor">@color/text_primary</item>
|
||||
</style>
|
||||
|
||||
|
|
@ -311,7 +312,7 @@
|
|||
|
||||
|
||||
<style name="PopupTheme" parent="Widget.AppCompat.PopupMenu.Overflow">
|
||||
<item name="android:popupBackground">@color/content_background</item>
|
||||
<item name="android:popupBackground">?attr/colorContentBackground</item>
|
||||
</style>
|
||||
|
||||
<style name="CardText">
|
||||
|
|
@ -595,7 +596,7 @@
|
|||
</style>
|
||||
|
||||
<style name="HabiticaButton.Content" parent="HabiticaButton">
|
||||
<item name="android:backgroundTint">@color/content_background</item>
|
||||
<item name="android:backgroundTint">?attr/colorContentBackground</item>
|
||||
<item name="android:textColor">@color/text_primary</item>
|
||||
</style>
|
||||
|
||||
|
|
@ -708,7 +709,7 @@
|
|||
</style>
|
||||
|
||||
<style name="HabiticaButton.Gray" parent="HabiticaButton">
|
||||
<item name="android:backgroundTint">@color/window_background</item>
|
||||
<item name="android:backgroundTint">?attr/colorWindowBackground</item>
|
||||
<item name="android:textColor">@color/text_brand_neon</item>
|
||||
</style>
|
||||
|
||||
|
|
@ -975,8 +976,8 @@
|
|||
</style>
|
||||
|
||||
<style name="Widget.App.BottomSheet.Modal" parent="Widget.MaterialComponents.BottomSheet.Modal">
|
||||
<item name="android:backgroundTint">@color/window_background</item>
|
||||
<item name="backgroundTint">@color/window_background</item>
|
||||
<item name="android:backgroundTint">?attr/colorWindowBackground</item>
|
||||
<item name="backgroundTint">?attr/colorWindowBackground</item>
|
||||
<item name="android:background">@drawable/bottom_sheet_background</item>
|
||||
<item name="shapeAppearanceOverlay">@null</item>
|
||||
<item name="shapeAppearance">@null</item>
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
device.activities.isCurrent(TaskFormActivity::class.java)
|
||||
textEditText.typeText("New Habit")
|
||||
KButton { withId(R.id.action_save) }.click()
|
||||
verify(exactly = 1) { taskRepository.createTaskInBackground(any()) }
|
||||
verify(exactly = 1) { taskRepository.createTaskInBackground(any(), assignChanges) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
screen {
|
||||
toolbar {
|
||||
KView { withId(R.id.action_save) }.click()
|
||||
verify(exactly = 1) { taskRepository.updateTaskInBackground(any()) }
|
||||
verify(exactly = 1) { taskRepository.updateTaskInBackground(any(), assignChanges) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -288,7 +288,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, TaskType.DAILY.value)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id!!)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns Flowable.just(task)
|
||||
justRun { taskRepository.updateTaskInBackground(capture(taskSlot)) }
|
||||
justRun { taskRepository.updateTaskInBackground(capture(taskSlot), assignChanges) }
|
||||
|
||||
val intent = Intent(ApplicationProvider.getApplicationContext(), TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
|
@ -313,7 +313,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
typeText("3")
|
||||
}
|
||||
KButton { withId(R.id.action_save) }.click()
|
||||
verify { taskRepository.updateTaskInBackground(any()) }
|
||||
verify { taskRepository.updateTaskInBackground(any(), assignChanges) }
|
||||
assert(taskSlot.captured.everyX == 3)
|
||||
assert(taskSlot.captured.frequency == Frequency.WEEKLY)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -445,4 +445,10 @@ interface ApiService {
|
|||
|
||||
@GET("tasks/group/{groupID}")
|
||||
suspend fun getTeamPlanTasks(@Path("groupID") groupId: String): HabitResponse<TaskList>
|
||||
|
||||
@POST("tasks/{taskID}/assign")
|
||||
suspend fun assignToTask(@Path("taskID") taskId: String?, @Body ids: List<String>): HabitResponse<Task>
|
||||
|
||||
@POST("tasks/{taskID}/unassign/{userID}")
|
||||
suspend fun unassignFromTask(@Path("taskID") taskID: String, @Path("userID") userID: String): HabitResponse<Task>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,4 +270,6 @@ interface ApiClient {
|
|||
suspend fun blockMember(userID: String): List<String>?
|
||||
suspend fun getTeamPlans(): List<TeamPlan>?
|
||||
suspend fun getTeamPlanTasks(teamID: String): TaskList?
|
||||
suspend fun assignToTask(taskId: String, ids: List<String>): Task?
|
||||
suspend fun unassignFromTask(taskId: String, userID: String): Task?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ interface TaskRepository : BaseRepository {
|
|||
|
||||
fun getUnmanagedTask(taskid: String): Flow<Task>
|
||||
|
||||
fun updateTaskInBackground(task: Task)
|
||||
fun updateTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>)
|
||||
|
||||
fun createTaskInBackground(task: Task)
|
||||
fun createTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>)
|
||||
|
||||
fun getTaskCopies(userId: String): Flow<List<Task>>
|
||||
|
||||
|
|
|
|||
|
|
@ -79,5 +79,5 @@ interface UserRepository : BaseRepository {
|
|||
suspend fun retrieveTeamPlans(): List<TeamPlan>?
|
||||
fun getTeamPlans(): Flow<List<TeamPlan>>
|
||||
suspend fun retrieveTeamPlan(teamID: String): Group?
|
||||
fun getTeamPlan(teamID: String): Flow<Group>
|
||||
fun getTeamPlan(teamID: String): Flow<Group?>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -771,6 +771,14 @@ class ApiClientImpl(
|
|||
return processResponse(apiService.getTeamPlanTasks(teamID))
|
||||
}
|
||||
|
||||
override suspend fun assignToTask(taskId: String, ids: List<String>): Task? {
|
||||
return process { apiService.assignToTask(taskId, ids) }
|
||||
}
|
||||
|
||||
override suspend fun unassignFromTask(taskId: String, userID: String): Task? {
|
||||
return process { apiService.unassignFromTask(taskId, userID) }
|
||||
}
|
||||
|
||||
override suspend fun bulkAllocatePoints(
|
||||
strength: Int,
|
||||
intelligence: Int,
|
||||
|
|
|
|||
|
|
@ -294,15 +294,40 @@ class TaskRepositoryImpl(
|
|||
|
||||
override fun getUnmanagedTask(taskid: String) = getTask(taskid).map { localRepository.getUnmanagedCopy(it) }
|
||||
|
||||
override fun updateTaskInBackground(task: Task) {
|
||||
override fun updateTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
||||
MainScope().launchCatching {
|
||||
updateTask(task)
|
||||
val updatedTask = updateTask(task) ?: return@launchCatching
|
||||
handleAssignmentChanges(updatedTask, assignChanges)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createTaskInBackground(task: Task) {
|
||||
override fun createTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
||||
MainScope().launchCatching {
|
||||
createTask(task)
|
||||
val createdTask = createTask(task) ?: return@launchCatching
|
||||
handleAssignmentChanges(createdTask, assignChanges)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleAssignmentChanges(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
||||
val taskID = task.id ?: return
|
||||
assignChanges["assign"]?.let { assignments ->
|
||||
if (assignments.isEmpty()) return@let
|
||||
val savedTask = apiClient.assignToTask(taskID, assignments) ?: return@let
|
||||
savedTask.id = task.id
|
||||
savedTask.position = task.position
|
||||
localRepository.save(task)
|
||||
}
|
||||
|
||||
assignChanges["unassign"]?.let { unassignments ->
|
||||
var savedTask: Task? = null
|
||||
for (unassignment in unassignments) {
|
||||
savedTask = apiClient.unassignFromTask(taskID, unassignment)
|
||||
}
|
||||
if (savedTask != null) {
|
||||
savedTask.id = task.id
|
||||
savedTask.position = task.position
|
||||
localRepository.save(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.habitrpg.shared.habitica.models.responses.TaskDirection
|
|||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.util.Date
|
||||
import java.util.GregorianCalendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
|
@ -366,8 +367,11 @@ class UserRepositoryImpl(
|
|||
return team
|
||||
}
|
||||
|
||||
override fun getTeamPlan(teamID: String): Flow<Group> {
|
||||
override fun getTeamPlan(teamID: String): Flow<Group?> {
|
||||
return localRepository.getTeamPlan(teamID)
|
||||
.map {
|
||||
it ?: retrieveTeamPlan(teamID)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getLiveUser(): User? {
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ interface UserLocalRepository : BaseLocalRepository {
|
|||
fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>>
|
||||
fun getUserQuestStatus(userID: String): Flow<UserQuestStatus>
|
||||
fun getTeamPlans(userID: String): Flow<List<TeamPlan>>
|
||||
fun getTeamPlan(teamID: String): Flow<Group>
|
||||
fun getTeamPlan(teamID: String): Flow<Group?>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,15 +124,14 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getTeamPlan(teamID: String): Flow<Group> {
|
||||
override fun getTeamPlan(teamID: String): Flow<Group?> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
return realm.where(Group::class.java)
|
||||
.equalTo("id", teamID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid && !realmObject.isEmpty() }
|
||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isValid }
|
||||
.map { teams -> teams.firstOrNull() }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getSkills(user: User): Flow<List<Skill>> {
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ import com.habitrpg.android.habitica.models.tasks.Task
|
|||
interface GroupPlanInfoProvider {
|
||||
fun assignedTextForTask(resources: Resources, assignedUsers: List<String>): String
|
||||
fun canScoreTask(task: Task): Boolean
|
||||
fun canEditTask(task: Task): Boolean
|
||||
suspend fun canEditTask(task: Task): Boolean
|
||||
suspend fun canAddTasks(): Boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.habitrpg.android.habitica.helpers
|
|||
import android.content.Context
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.extensions.nameRes
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskDifficulty
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
|
|
@ -41,12 +43,6 @@ class TaskDescriptionBuilder(private val context: Context) {
|
|||
}
|
||||
|
||||
private fun describeDifficulty(difficulty: Float): String {
|
||||
return when (difficulty) {
|
||||
0.1f -> context.getString(R.string.trivial)
|
||||
1.0f -> context.getString(R.string.easy)
|
||||
1.5f -> context.getString(R.string.medium)
|
||||
2.0f -> context.getString(R.string.hard)
|
||||
else -> ""
|
||||
}
|
||||
return context.getString(TaskDifficulty.valueOf(difficulty).nameRes)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.habitrpg.android.habitica.models
|
||||
|
||||
import com.habitrpg.shared.habitica.models.Avatar
|
||||
|
||||
interface Assignable {
|
||||
val id: String?
|
||||
val avatar: Avatar?
|
||||
val identifiableName: String
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.models.members
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.habitrpg.android.habitica.models.Assignable
|
||||
import com.habitrpg.android.habitica.models.BaseMainObject
|
||||
import com.habitrpg.android.habitica.models.social.UserParty
|
||||
import com.habitrpg.android.habitica.models.user.Authentication
|
||||
|
|
@ -16,11 +17,11 @@ import io.realm.RealmModel
|
|||
import io.realm.RealmObject
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
open class Member : RealmObject(), Avatar, BaseMainObject {
|
||||
open class Member : RealmObject(), Avatar, BaseMainObject, Assignable {
|
||||
|
||||
@PrimaryKey
|
||||
@SerializedName("_id")
|
||||
var id: String? = null
|
||||
override var id: String? = null
|
||||
override var stats: Stats? = null
|
||||
var inbox: Inbox? = null
|
||||
override var preferences: MemberPreferences? = null
|
||||
|
|
@ -50,6 +51,12 @@ open class Member : RealmObject(), Avatar, BaseMainObject {
|
|||
""
|
||||
} else this.profile?.name ?: ""
|
||||
|
||||
override val identifiableName: String
|
||||
get() = username ?: ""
|
||||
|
||||
override val avatar: Avatar
|
||||
get() = this
|
||||
|
||||
val petsFoundCount: Int
|
||||
get() = this.items?.pets?.size ?: 0
|
||||
val mountsTamedCount: Int
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.habitrpg.android.habitica.models.social
|
|||
import com.google.gson.annotations.SerializedName
|
||||
import com.habitrpg.android.habitica.models.BaseMainObject
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||
import io.realm.RealmList
|
||||
import io.realm.RealmObject
|
||||
|
|
@ -27,6 +26,7 @@ open class Group : RealmObject(), BaseMainObject {
|
|||
var summary: String? = null
|
||||
var leaderID: String? = null
|
||||
var leaderName: String? = null
|
||||
var managers: RealmList<String>? = null
|
||||
var name: String? = null
|
||||
var memberCount: Int = 0
|
||||
var type: String? = null
|
||||
|
|
@ -54,6 +54,13 @@ open class Group : RealmObject(), BaseMainObject {
|
|||
return id.hashCode()
|
||||
}
|
||||
|
||||
fun hasTaskEditPrivileges(userID: String): Boolean {
|
||||
if (leaderID == userID) {
|
||||
return true
|
||||
}
|
||||
return managers?.contains(userID) == true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAVERN_ID = "00000000-0000-4000-A000-000000000000"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class UserRepositoryModule {
|
|||
}
|
||||
|
||||
@Provides
|
||||
@UserScope
|
||||
fun providesTaskRepository(
|
||||
localRepository: TaskLocalRepository,
|
||||
apiClient: ApiClient,
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ class FullProfileActivity : BaseActivity() {
|
|||
R.color.transparent
|
||||
)
|
||||
)
|
||||
binding.avatarWithBars.hpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
binding.avatarWithBars.xpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
binding.avatarWithBars.mpBar.barBackgroundColor = getThemeColor(R.color.window_background)
|
||||
binding.avatarWithBars.hpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
binding.avatarWithBars.xpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
binding.avatarWithBars.mpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
|
||||
attributeRows.clear()
|
||||
binding.attributesCardView.setOnClickListener { toggleAttributeDetails() }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,48 @@ import android.view.WindowManager
|
|||
import android.widget.CheckBox
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatCheckBox
|
||||
import androidx.compose.animation.animateColor
|
||||
import androidx.compose.animation.core.FastOutLinearInEasing
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.children
|
||||
|
|
@ -27,6 +69,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.data.TagRepository
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.databinding.ActivityTaskFormBinding
|
||||
|
|
@ -35,17 +78,26 @@ import com.habitrpg.android.habitica.extensions.addCancelButton
|
|||
import com.habitrpg.android.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.helpers.launchCatching
|
||||
import com.habitrpg.android.habitica.models.Assignable
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskGroupPlan
|
||||
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.CompletedAt
|
||||
import com.habitrpg.android.habitica.ui.views.UserRow
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.showAsBottomSheet
|
||||
import com.habitrpg.android.habitica.ui.views.tasks.form.TaskDifficultySelector
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.shared.habitica.models.tasks.Attribute
|
||||
import com.habitrpg.shared.habitica.models.tasks.Frequency
|
||||
import com.habitrpg.shared.habitica.models.tasks.HabitResetOption
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskDifficulty
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import io.realm.RealmList
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
|
@ -78,6 +130,9 @@ class TaskFormActivity : BaseActivity() {
|
|||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
private var challenge: Challenge? = null
|
||||
|
||||
private var isCreating = true
|
||||
|
|
@ -87,6 +142,10 @@ class TaskFormActivity : BaseActivity() {
|
|||
private var initialTaskInstance: Task? = null
|
||||
private var taskType: TaskType = TaskType.HABIT
|
||||
private var tags = listOf<Tag>()
|
||||
private var groupID: String? = null
|
||||
private var groupMembers = listOf<Member>()
|
||||
private var assignedIDs = mutableStateListOf<String>()
|
||||
private var taskCompletedMap = mutableStateMapOf<String, Date>()
|
||||
private var preselectedTags: ArrayList<String>? = null
|
||||
private var hasPreselectedTags = false
|
||||
private var selectedStat = Attribute.STRENGTH
|
||||
|
|
@ -98,10 +157,11 @@ class TaskFormActivity : BaseActivity() {
|
|||
private var isDiscardCancelled: Boolean = false
|
||||
private var canSave: Boolean = false
|
||||
|
||||
private var taskDifficulty = mutableStateOf(TaskDifficulty.EASY)
|
||||
|
||||
private var tintColor: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
binding.taskDifficultyButtons.tintColor = value
|
||||
binding.habitScoringButtons.tintColor = value
|
||||
binding.habitResetStreakButtons.tintColor = value
|
||||
binding.taskSchedulingControls.tintColor = value
|
||||
|
|
@ -126,6 +186,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
val bundle = intent.extras ?: return
|
||||
|
||||
val taskId = bundle.getString(TASK_ID_KEY)
|
||||
groupID = bundle.getString(GROUP_ID_KEY)
|
||||
forcedIsNight = false
|
||||
forcedTheme = if (taskId != null) {
|
||||
val taskValue = bundle.getDouble(TASK_VALUE_KEY)
|
||||
|
|
@ -144,13 +205,9 @@ class TaskFormActivity : BaseActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (forcedTheme == "yellow") {
|
||||
binding.taskDifficultyButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_yellow)
|
||||
binding.habitScoringButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_yellow)
|
||||
} else if (forcedTheme == "taskform") {
|
||||
binding.taskDifficultyButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
binding.habitScoringButtons.textTintColor =
|
||||
ContextCompat.getColor(this, R.color.text_brand_neon)
|
||||
}
|
||||
|
|
@ -210,6 +267,32 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
if (groupID != null) {
|
||||
binding.assignView.setContent {
|
||||
HabiticaTheme {
|
||||
AssignedView(
|
||||
groupMembers.filter { assignedIDs.contains(it.id) },
|
||||
taskCompletedMap,
|
||||
task?.extraExtraLightTaskColor?.let { colorResource(it) } ?: Color(getThemeColor(R.attr.colorTintedBackgroundOffset)),
|
||||
colorResource(task?.darkestTaskColor ?: R.color.text_primary),
|
||||
{
|
||||
showAssignDialog()
|
||||
},
|
||||
showEditButton = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launchCatching {
|
||||
socialRepository.getGroupMembers(groupID ?: "").collect {
|
||||
groupMembers = it
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.assignTitleView.visibility = View.GONE
|
||||
binding.assignView.visibility = View.GONE
|
||||
}
|
||||
|
||||
title = ""
|
||||
when {
|
||||
taskId != null -> {
|
||||
|
|
@ -237,10 +320,11 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
bundle.containsKey(PARCELABLE_TASK) -> {
|
||||
isCreating = false
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
task = bundle.getParcelable(PARCELABLE_TASK, Task::class.java)
|
||||
task = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
bundle.getParcelable(PARCELABLE_TASK, Task::class.java)
|
||||
} else {
|
||||
task = bundle.getParcelable(PARCELABLE_TASK)
|
||||
@Suppress("DEPRECATION")
|
||||
bundle.getParcelable(PARCELABLE_TASK)
|
||||
}
|
||||
task?.let { fillForm(it) }
|
||||
}
|
||||
|
|
@ -259,6 +343,13 @@ class TaskFormActivity : BaseActivity() {
|
|||
initialTaskInstance = configureTask(Task())
|
||||
}
|
||||
}
|
||||
|
||||
binding.taskDifficultyButtons.setContent {
|
||||
HabiticaTheme {
|
||||
TaskDifficultySelector(taskDifficulty.value, onSelect = { taskDifficulty.value = it })
|
||||
}
|
||||
}
|
||||
|
||||
configureForm()
|
||||
}
|
||||
|
||||
|
|
@ -385,6 +476,11 @@ class TaskFormActivity : BaseActivity() {
|
|||
if (isCreating) {
|
||||
binding.adjustStreakTitleView.visibility = View.GONE
|
||||
binding.adjustStreakWrapper.visibility = View.GONE
|
||||
|
||||
if (groupID != null) {
|
||||
binding.habitResetStreakTitleView.visibility = View.GONE
|
||||
binding.habitResetStreakButtons.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +519,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
canSave = true
|
||||
binding.textEditText.setText(task.text)
|
||||
binding.notesEditText.setText(task.notes)
|
||||
binding.taskDifficultyButtons.selectedDifficulty = task.priority
|
||||
taskDifficulty.value = TaskDifficulty.valueOf(task.priority)
|
||||
when (taskType) {
|
||||
TaskType.HABIT -> {
|
||||
binding.habitScoringButtons.isPositive = task.up ?: false
|
||||
|
|
@ -461,6 +557,22 @@ class TaskFormActivity : BaseActivity() {
|
|||
task.reminders?.let { binding.remindersContainer.reminders = it }
|
||||
}
|
||||
task.attribute?.let { selectedStat = it }
|
||||
|
||||
if (task.isGroupTask) {
|
||||
(binding.habitAdjustPositiveStreakView.parent as ViewGroup).visibility = View.GONE
|
||||
(binding.habitAdjustNegativeStreakView.parent as ViewGroup).visibility = View.GONE
|
||||
binding.statWrapper.visibility = View.GONE
|
||||
binding.habitResetStreakTitleView.visibility = View.GONE
|
||||
binding.habitResetStreakButtons.visibility = View.GONE
|
||||
|
||||
assignedIDs = task.group?.assignedUsersDetail?.map { it.assignedUserID }?.filterNotNull()?.toMutableStateList() ?: mutableStateListOf()
|
||||
task.group?.assignedUsersDetail?.forEach {
|
||||
it.completedDate?.let { date ->
|
||||
taskCompletedMap[it.assignedUserID ?: ""] = date
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setAllTagSelections()
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +623,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
|
||||
thisTask.text = binding.textEditText.text.toString()
|
||||
thisTask.notes = binding.notesEditText.text.toString()
|
||||
thisTask.priority = binding.taskDifficultyButtons.selectedDifficulty
|
||||
thisTask.priority = taskDifficulty.value.value
|
||||
if (usesTaskAttributeStats) {
|
||||
thisTask.attribute = selectedStat
|
||||
}
|
||||
|
|
@ -553,6 +665,13 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
if (groupID != null) {
|
||||
if (thisTask.group?.groupID != groupID) {
|
||||
thisTask.group = TaskGroupPlan()
|
||||
thisTask.group?.groupID = groupID
|
||||
}
|
||||
}
|
||||
|
||||
return thisTask
|
||||
}
|
||||
|
||||
|
|
@ -574,11 +693,29 @@ class TaskFormActivity : BaseActivity() {
|
|||
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra(TASK_TYPE_KEY, taskType.value)
|
||||
|
||||
val assignChanges = mapOf(
|
||||
"assign" to mutableListOf<String>(),
|
||||
"unassign" to mutableListOf<String>()
|
||||
)
|
||||
if (thisTask.isGroupTask) {
|
||||
for (id in assignedIDs) {
|
||||
if (thisTask.group?.assignedUsersDetail?.firstOrNull { it.assignedUserID == id } == null) {
|
||||
assignChanges["assign"]?.add(id)
|
||||
}
|
||||
}
|
||||
for (details in thisTask.group?.assignedUsersDetail ?: listOf()) {
|
||||
if (assignedIDs.firstOrNull { it == details.assignedUserID } == null) {
|
||||
details.assignedUserID?.let { assignChanges["unassign"]?.add(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isChallengeTask) {
|
||||
if (isCreating) {
|
||||
taskRepository.createTaskInBackground(thisTask)
|
||||
taskRepository.createTaskInBackground(thisTask, assignChanges)
|
||||
} else {
|
||||
taskRepository.updateTaskInBackground(thisTask)
|
||||
taskRepository.updateTaskInBackground(thisTask, assignChanges)
|
||||
}
|
||||
if (isDiscardCancelled) {
|
||||
analyticsManager.logEvent("back_to_task", bundleOf(Pair("is_creating", isCreating)))
|
||||
|
|
@ -626,7 +763,8 @@ class TaskFormActivity : BaseActivity() {
|
|||
|
||||
private fun showChallengeDeleteTask() {
|
||||
lifecycleScope.launchCatching {
|
||||
val tasks = taskRepository.getTasksForChallenge(task?.challengeID).firstOrNull() ?: return@launchCatching
|
||||
val tasks = taskRepository.getTasksForChallenge(task?.challengeID).firstOrNull()
|
||||
?: return@launchCatching
|
||||
val taskCount = tasks.size
|
||||
val alert = HabiticaAlertDialog(this@TaskFormActivity)
|
||||
alert.setTitle(getString(R.string.delete_challenge_task_title))
|
||||
|
|
@ -673,39 +811,40 @@ class TaskFormActivity : BaseActivity() {
|
|||
return
|
||||
}
|
||||
lifecycleScope.launchCatching {
|
||||
val tasks = taskRepository.getTasksForChallenge(task.challengeID).firstOrNull() ?: return@launchCatching
|
||||
val taskCount = tasks.size
|
||||
val dialog = HabiticaAlertDialog(this@TaskFormActivity)
|
||||
dialog.setTitle(R.string.broken_challenge)
|
||||
dialog.setMessage(
|
||||
getString(
|
||||
R.string.broken_challenge_description,
|
||||
taskCount
|
||||
)
|
||||
)
|
||||
dialog.addButton(
|
||||
getString(R.string.keep_x_tasks, taskCount),
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "keep-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.addButton(
|
||||
getString(R.string.delete_x_tasks, taskCount),
|
||||
false,
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
val tasks = taskRepository.getTasksForChallenge(task.challengeID).firstOrNull()
|
||||
?: return@launchCatching
|
||||
val taskCount = tasks.size
|
||||
val dialog = HabiticaAlertDialog(this@TaskFormActivity)
|
||||
dialog.setTitle(R.string.broken_challenge)
|
||||
dialog.setMessage(
|
||||
getString(
|
||||
R.string.broken_challenge_description,
|
||||
taskCount
|
||||
)
|
||||
)
|
||||
dialog.addButton(
|
||||
getString(R.string.keep_x_tasks, taskCount),
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "keep-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.addButton(
|
||||
getString(R.string.delete_x_tasks, taskCount),
|
||||
false,
|
||||
true
|
||||
) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "remove-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.setExtraCloseButtonVisibility(View.VISIBLE)
|
||||
dialog.show()
|
||||
}
|
||||
taskRepository.unlinkAllTasks(task.challengeID, "remove-all")
|
||||
userRepository.retrieveUser(true, true)
|
||||
}
|
||||
}
|
||||
dialog.setExtraCloseButtonVisibility(View.VISIBLE)
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableEditingForUneditableFieldsInChallengeTask() {
|
||||
|
|
@ -720,9 +859,26 @@ class TaskFormActivity : BaseActivity() {
|
|||
super.finish()
|
||||
}
|
||||
|
||||
private fun showAssignDialog() {
|
||||
showAsBottomSheet {
|
||||
AssignSheet(
|
||||
groupMembers,
|
||||
assignedIDs,
|
||||
{
|
||||
if (assignedIDs.contains(it)) {
|
||||
assignedIDs.remove(it)
|
||||
} else {
|
||||
assignedIDs.add(it)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SELECTED_TAGS_KEY = "selectedTags"
|
||||
const val TASK_ID_KEY = "taskId"
|
||||
const val GROUP_ID_KEY = "groupId"
|
||||
const val TASK_VALUE_KEY = "taskValue"
|
||||
const val USER_ID_KEY = "userId"
|
||||
const val TASK_TYPE_KEY = "type"
|
||||
|
|
@ -742,3 +898,142 @@ private fun String.toIntCatchOverflow(): Int? {
|
|||
0
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AssignedView(
|
||||
assigned: List<Assignable>,
|
||||
completedAt: Map<String, Date>,
|
||||
backgroundColor: Color,
|
||||
color: Color,
|
||||
onEditClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
showEditButton: Boolean = false
|
||||
) {
|
||||
Column(modifier.fillMaxWidth()) {
|
||||
val rowModifier = Modifier
|
||||
.padding(vertical = 4.dp)
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(8.dp)
|
||||
)
|
||||
.padding(15.dp, 12.dp)
|
||||
.heightIn(min = 24.dp)
|
||||
.fillMaxWidth()
|
||||
for (assignable in assigned) {
|
||||
UserRow(
|
||||
username = assignable.identifiableName, modifier = rowModifier,
|
||||
color = color,
|
||||
extraContent = {
|
||||
completedAt[assignable.id]?.let { CompletedAt(completedAt = it) }
|
||||
}
|
||||
)
|
||||
}
|
||||
if (showEditButton) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier
|
||||
.clickable {
|
||||
onEditClick()
|
||||
}
|
||||
.padding(vertical = 4.dp)
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(8.dp)
|
||||
)
|
||||
.padding(15.dp, 12.dp)
|
||||
.heightIn(min = 24.dp)
|
||||
.fillMaxWidth()) {
|
||||
Image(
|
||||
painterResource(R.drawable.edit),
|
||||
null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colors.primary)
|
||||
)
|
||||
Text(stringResource(R.string.edit_assignees), color = color,
|
||||
modifier = Modifier.padding(start = 4.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AssignSheet(
|
||||
members: List<Member>,
|
||||
assignedMembers: List<String>,
|
||||
onAssignClick: (String) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(modifier) {
|
||||
Box {
|
||||
Text(
|
||||
stringResource(R.string.assign_to),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = colorResource(R.color.gray_200),
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp)
|
||||
)
|
||||
TextButton(
|
||||
onClick = {
|
||||
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(),
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
) {
|
||||
Text(stringResource(R.string.done))
|
||||
}
|
||||
}
|
||||
for (member in members) {
|
||||
val isAssigned = assignedMembers.contains(member.id)
|
||||
val transition = updateTransition(isAssigned, label = "isAssigned")
|
||||
val rotation = transition.animateFloat(label = "isAssigned", transitionSpec = { spring(Spring.DampingRatioLowBouncy, Spring.StiffnessLow) }) {
|
||||
if (it) 0f else 45f
|
||||
}
|
||||
val backgroundColor = transition.animateColor(label = "isAssigned", transitionSpec = { tween(400, easing = FastOutLinearInEasing) }) {
|
||||
if (it) MaterialTheme.colors.primary else colorResource(id = R.color.transparent)
|
||||
}
|
||||
val color = transition.animateColor(label = "isAssigned", transitionSpec = { tween(400, easing = FastOutLinearInEasing) }) {
|
||||
fadeIn(tween(10000))
|
||||
colorResource(if (it) R.color.white else R.color.text_dimmed)
|
||||
}
|
||||
val borderColor = transition.animateColor(label = "isAssigned", transitionSpec = { tween(400, easing = FastOutLinearInEasing) }) {
|
||||
fadeIn(tween(10000))
|
||||
if (it) MaterialTheme.colors.primary else colorResource(id = R.color.text_dimmed)
|
||||
}
|
||||
UserRow(
|
||||
username = member.displayName,
|
||||
color = colorResource(R.color.text_primary),
|
||||
extraContent = {
|
||||
Text(
|
||||
member.formattedUsername ?: "",
|
||||
color = colorResource(R.color.text_ternary)
|
||||
)
|
||||
}, endContent = {
|
||||
Image(
|
||||
painterResource(R.drawable.ic_close_white_24dp),
|
||||
null,
|
||||
colorFilter = ColorFilter.tint(color.value),
|
||||
modifier = Modifier
|
||||
.rotate(rotation.value)
|
||||
.size(24.dp)
|
||||
.background(
|
||||
backgroundColor.value,
|
||||
CircleShape
|
||||
)
|
||||
.border(
|
||||
2.dp,
|
||||
borderColor.value,
|
||||
CircleShape
|
||||
)
|
||||
.padding(3.dp)
|
||||
)
|
||||
}, modifier = Modifier
|
||||
.clickable {
|
||||
member.id?.let { onAssignClick(it) }
|
||||
}
|
||||
.padding(30.dp, 12.dp)
|
||||
.heightIn(min = 24.dp)
|
||||
.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
|
|
@ -23,7 +22,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
|
|
@ -48,8 +46,9 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController
|
|||
import com.habitrpg.android.habitica.helpers.TaskDescriptionBuilder
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.CompletedAt
|
||||
import com.habitrpg.android.habitica.ui.views.UserRow
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import java.text.DateFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
class TaskSummaryViewModel(val taskId: String) : BaseViewModel() {
|
||||
|
|
@ -100,7 +99,6 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
val task by viewModel.task.observeAsState()
|
||||
val titleModifier = Modifier.padding(top = 30.dp)
|
||||
val textModifier = Modifier.padding(top = 4.dp)
|
||||
val completedTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT)
|
||||
if (task != null) {
|
||||
val darkestColor = colorResource(task?.darkestTaskColor ?: R.color.text_primary)
|
||||
val systemUiController = rememberSystemUiController()
|
||||
|
|
@ -245,18 +243,7 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
.fillMaxWidth(),
|
||||
color = darkestColor,
|
||||
extraContent = if (item.completed) ({
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(top = 4.dp)
|
||||
) {
|
||||
Image(painterResource(R.drawable.completed), null)
|
||||
Text(stringResource(R.string.completed_at,
|
||||
item.completedDate?.let { completedTimeFormat.format(it) }
|
||||
?: ""),
|
||||
fontSize = 14.sp,
|
||||
color = colorResource(R.color.green_10),
|
||||
modifier = Modifier.padding(start = 4.dp))
|
||||
}
|
||||
CompletedAt(item.completedDate)
|
||||
}) else null
|
||||
)
|
||||
}
|
||||
|
|
@ -281,26 +268,6 @@ private fun String.makeBoldComposable(): AnnotatedString {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UserRow(
|
||||
username: String,
|
||||
modifier: Modifier = Modifier,
|
||||
extraContent: @Composable (() -> Unit)? = null,
|
||||
color: Color? = null
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
|
||||
Column {
|
||||
Text(
|
||||
"@$username", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = color ?: MaterialTheme.colors.primary, modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
)
|
||||
if (extraContent != null) {
|
||||
extraContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun TaskSummaryViewPreview() {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import com.habitrpg.common.habitica.helpers.EmptyItem
|
|||
import com.habitrpg.shared.habitica.models.responses.TaskDirection
|
||||
import com.habitrpg.shared.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||
|
|
@ -58,6 +59,7 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -561,12 +563,18 @@ private fun openTaskForm(task: Task) {
|
|||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, task.type?.value)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id)
|
||||
bundle.putString(TaskFormActivity.GROUP_ID_KEY, task.group?.groupID)
|
||||
bundle.putDouble(TaskFormActivity.TASK_VALUE_KEY, task.value)
|
||||
|
||||
if (viewModel.canEditTask(task)) {
|
||||
MainNavigationController.navigate(R.id.taskFormActivity, bundle)
|
||||
} else {
|
||||
MainNavigationController.navigate(R.id.taskSummaryActivity, bundle)
|
||||
lifecycleScope.launchCatching {
|
||||
val id = if (viewModel.canEditTask(task)) {
|
||||
R.id.taskFormActivity
|
||||
} else {
|
||||
R.id.taskSummaryActivity
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
MainNavigationController.navigate(id, bundle)
|
||||
}
|
||||
}
|
||||
TasksFragment.lastTaskFormOpen = Date()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,9 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
|
|||
}
|
||||
binding?.viewPager?.currentItem = binding?.viewPager?.currentItem ?: 0
|
||||
bottomNavigation?.listener = this
|
||||
bottomNavigation?.canAddTasks = viewModel.isPersonalBoard
|
||||
lifecycleScope.launchCatching {
|
||||
bottomNavigation?.canAddTasks = viewModel.canAddTasks()
|
||||
}
|
||||
|
||||
activity?.binding?.content?.toolbarTitle?.setOnClickListener {
|
||||
viewModel.cycleOwnerIDs()
|
||||
|
|
@ -324,6 +326,9 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
|
|||
|
||||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type.value)
|
||||
if (!viewModel.isPersonalBoard) {
|
||||
bundle.putString(TaskFormActivity.GROUP_ID_KEY, viewModel.ownerID.value)
|
||||
}
|
||||
bundle.putStringArrayList(TaskFormActivity.SELECTED_TAGS_KEY, ArrayList(viewModel.tags))
|
||||
|
||||
val intent = Intent(activity, TaskFormActivity::class.java)
|
||||
|
|
@ -417,7 +422,8 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
|
|||
activity?.title = viewModel.ownerTitle
|
||||
}
|
||||
viewModel.userViewModel.currentTeamPlan.value = viewModel.teamPlans[viewModel.ownerID.value]
|
||||
val isPersonalBoard = viewModel.isPersonalBoard
|
||||
bottomNavigation?.canAddTasks = isPersonalBoard
|
||||
lifecycleScope.launchCatching {
|
||||
bottomNavigation?.canAddTasks = viewModel.canAddTasks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import io.realm.Case
|
|||
import io.realm.OrderedRealmCollection
|
||||
import io.realm.RealmQuery
|
||||
import io.realm.Sort
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
|
|
@ -310,11 +311,22 @@ class TasksViewModel : BaseViewModel(), GroupPlanInfoProvider {
|
|||
return task.isAssignedToUser(userViewModel.userID) || task.group?.assignedUsers?.isEmpty() != false
|
||||
}
|
||||
|
||||
override fun canEditTask(task: Task): Boolean {
|
||||
override suspend fun canEditTask(task: Task): Boolean {
|
||||
if (!task.isGroupTask) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
val groupID = task.group?.groupID ?: return true
|
||||
val group = userRepository.getTeamPlan(groupID).firstOrNull()
|
||||
return group?.hasTaskEditPrivileges(userViewModel.userID) ?: false
|
||||
}
|
||||
|
||||
override suspend fun canAddTasks(): Boolean {
|
||||
if (isPersonalBoard) {
|
||||
return true
|
||||
}
|
||||
val groupID = ownerID.value ?: return true
|
||||
val group = userRepository.getTeamPlan(groupID).firstOrNull()
|
||||
return group?.hasTaskEditPrivileges(userViewModel.userID) ?: false
|
||||
}
|
||||
|
||||
override fun assignedTextForTask(resources: Resources, assignedUsers: List<String>): String {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
|
|
@ -25,8 +23,6 @@ import androidx.compose.foundation.layout.size
|
|||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.ProgressIndicatorDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
|
|
@ -35,7 +31,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
|
@ -51,10 +46,6 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.common.habitica.helpers.NumberAbbreviator
|
||||
import java.lang.Double.max
|
||||
import java.math.RoundingMode
|
||||
import java.text.NumberFormat
|
||||
|
||||
@Composable
|
||||
fun UserLevelText(user: User) {
|
||||
|
|
@ -77,36 +68,6 @@ fun UserLevelText(user: User) {
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CurrencyText(
|
||||
currency: String,
|
||||
value: Double,
|
||||
modifier: Modifier = Modifier,
|
||||
decimals: Int = 2,
|
||||
minForAbbrevation: Int = 0
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
when (currency) {
|
||||
"gold" -> HabiticaIconsHelper.imageOfGold()
|
||||
"gems" -> HabiticaIconsHelper.imageOfGem()
|
||||
"hourglasses" -> HabiticaIconsHelper.imageOfHourglass()
|
||||
else -> null
|
||||
}?.asImageBitmap()?.let { Image(it, null, Modifier.padding(end = 5.dp)) }
|
||||
Text(
|
||||
NumberAbbreviator.abbreviate(null, value, decimals, minForAbbrevation),
|
||||
color = when (currency) {
|
||||
"gold" -> colorResource(R.color.text_gold)
|
||||
"gems" -> colorResource(R.color.text_green)
|
||||
"hourglasses" -> colorResource(R.color.text_brand)
|
||||
else -> colorResource(R.color.text_primary)
|
||||
},
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppHeaderView(
|
||||
viewModel: MainUserViewModel,
|
||||
|
|
@ -245,60 +206,4 @@ fun AppHeaderView(
|
|||
CurrencyText("gems", user?.gemCount?.toDouble() ?: 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LabeledBar(
|
||||
icon: Bitmap,
|
||||
label: String,
|
||||
color: Color,
|
||||
value: Double,
|
||||
maxValue: Double,
|
||||
displayCompact: Boolean,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val formatter = NumberFormat.getInstance()
|
||||
formatter.maximumFractionDigits = 1
|
||||
formatter.roundingMode = RoundingMode.UP
|
||||
formatter.isGroupingUsed = true
|
||||
|
||||
val cleanedMaxVlaue = max(1.0, maxValue)
|
||||
|
||||
val animatedValue = animateFloatAsState(
|
||||
targetValue = value.toFloat(),
|
||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||
).value
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
|
||||
AnimatedVisibility(
|
||||
visible = !displayCompact,
|
||||
enter = slideInHorizontally { -18 },
|
||||
exit = slideOutHorizontally { -18 }) {
|
||||
Image(icon.asImageBitmap(), null, modifier = Modifier.padding(end = 8.dp))
|
||||
}
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
LinearProgressIndicator(
|
||||
progress = (animatedValue / cleanedMaxVlaue).toFloat(),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(CircleShape)
|
||||
.height(8.dp),
|
||||
backgroundColor = colorResource(R.color.window_background),
|
||||
color = color
|
||||
)
|
||||
AnimatedVisibility(visible = !displayCompact) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(top = 2.dp)
|
||||
) {
|
||||
Text(
|
||||
"${formatter.format(animatedValue)} / ${formatter.format(cleanedMaxVlaue)}",
|
||||
fontSize = 12.sp,
|
||||
color = colorResource(R.color.text_ternary)
|
||||
)
|
||||
Spacer(Modifier.weight(1f))
|
||||
Text(label, fontSize = 12.sp, color = colorResource(R.color.text_ternary))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Outline
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
|
||||
object AvatarCircleShape : Shape {
|
||||
override fun createOutline(
|
||||
size: Size,
|
||||
layoutDirection: LayoutDirection,
|
||||
density: Density
|
||||
): Outline =
|
||||
CircleShape.createOutline(size, 20f, 20f, 20f, 20f, layoutDirection)
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.ModalBottomSheetLayout
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
// Extension for Activity
|
||||
fun Activity.showAsBottomSheet(content: @Composable (() -> Unit) -> Unit) {
|
||||
val viewGroup = this.findViewById(android.R.id.content) as ViewGroup
|
||||
addContentToView(viewGroup, content)
|
||||
}
|
||||
|
||||
// Extension for Fragment
|
||||
fun Fragment.showAsBottomSheet(content: @Composable (() -> Unit) -> Unit) {
|
||||
val viewGroup = requireActivity().findViewById(android.R.id.content) as ViewGroup
|
||||
addContentToView(viewGroup, content)
|
||||
}
|
||||
|
||||
// Helper method
|
||||
private fun addContentToView(
|
||||
viewGroup: ViewGroup,
|
||||
content: @Composable (() -> Unit) -> Unit
|
||||
) {
|
||||
viewGroup.addView(
|
||||
ComposeView(viewGroup.context).apply {
|
||||
setContent {
|
||||
HabiticaTheme {
|
||||
BottomSheetWrapper(viewGroup, this, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun BottomSheetWrapper(
|
||||
parent: ViewGroup,
|
||||
composeView: ComposeView,
|
||||
content: @Composable (() -> Unit) -> Unit
|
||||
) {
|
||||
val TAG = parent::class.java.simpleName
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val modalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
var isSheetOpened by remember { mutableStateOf(false) }
|
||||
|
||||
ModalBottomSheetLayout(
|
||||
sheetBackgroundColor = Color.Transparent,
|
||||
sheetState = modalBottomSheetState,
|
||||
sheetContent = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.border(
|
||||
2.dp,
|
||||
colorResource(R.color.window_background),
|
||||
RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
|
||||
)
|
||||
.background(
|
||||
MaterialTheme.colors.background,
|
||||
RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
|
||||
)
|
||||
.padding(vertical = 8.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 16.dp)
|
||||
.background(colorResource(R.color.content_background_offset))
|
||||
.size(24.dp, 3.dp)
|
||||
)
|
||||
content {
|
||||
// Action passed for clicking close button in the content
|
||||
coroutineScope.launch {
|
||||
modalBottomSheetState.hide() // will trigger the LaunchedEffect
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
) {}
|
||||
|
||||
BackHandler {
|
||||
coroutineScope.launch {
|
||||
modalBottomSheetState.hide() // will trigger the LaunchedEffect
|
||||
}
|
||||
}
|
||||
|
||||
// Take action based on hidden state
|
||||
LaunchedEffect(modalBottomSheetState.currentValue) {
|
||||
when (modalBottomSheetState.currentValue) {
|
||||
ModalBottomSheetValue.Hidden -> {
|
||||
when {
|
||||
isSheetOpened -> parent.removeView(composeView)
|
||||
else -> {
|
||||
isSheetOpened = true
|
||||
modalBottomSheetState.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Log.i(TAG, "Bottom sheet ${modalBottomSheetState.currentValue} state")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue