begin implementing bulk allocation

This commit is contained in:
Phillip Thelen 2017-10-30 09:25:33 +01:00
parent 4d11bcf172
commit 0732b0500e
13 changed files with 344 additions and 18 deletions

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/gray_400"
android:orientation="vertical"
android:padding="18dp"
android:focusable="true"
android:focusableInTouchMode="true">
<TextView
android:id="@+id/allocatedTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="0/60"
android:gravity="center"
style="@style/Title2"
android:textColor="@color/white"
android:textStyle="bold"
android:padding="0dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/allocated"
android:gravity="center"
style="@style/Subheader3"
android:textColor="@color/white"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="18dp"
android:orientation="vertical">
<com.habitrpg.android.habitica.ui.views.StatsSliderView
android:id="@+id/strengthSliderView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:statsTitle="@string/str_abbrv"
app:statsColor="@color/red_100"
app:statsTextColor="@color/red_10"/>
<com.habitrpg.android.habitica.ui.views.StatsSliderView
android:id="@+id/intelligenceSliderView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:statsTitle="@string/int_abbrv"
app:statsColor="@color/blue_100"
app:statsTextColor="@color/blue_10"/>
<com.habitrpg.android.habitica.ui.views.StatsSliderView
android:id="@+id/constitutionSliderView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:statsTitle="@string/con_abbrv"
app:statsColor="@color/yellow_100"
app:statsTextColor="@color/yellow_10"/>
<com.habitrpg.android.habitica.ui.views.StatsSliderView
android:id="@+id/perceptionSliderView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:statsTitle="@string/per_abbrv"
app:statsColor="@color/brand_300"
app:statsTextColor="@color/brand_300"/>
</LinearLayout>
</LinearLayout>

View file

@ -16,6 +16,7 @@
android:paddingTop="12dp"
android:paddingBottom="20dp">
<LinearLayout
android:id="@+id/statsAllocationButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="android.widget.LinearLayout"
android:gravity="center_vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/statTypeTitle"
android:layout_width="35dp"
android:layout_height="wrap_content"
tools:text="STR"
tools:textColor="@color/red_50"
android:layout_marginRight="4dp"
style="@style/Body3"
android:textSize="16sp"
android:textAllCaps="true" />
<TextView
android:id="@+id/previousValueTextView"
android:layout_width="wrap_content"
android:minWidth="28dp"
android:layout_height="wrap_content"
tools:text="10"
android:textColor="@color/gray_100"
style="@style/Body3"
android:textSize="16sp"
android:gravity="right"/>
<SeekBar
android:id="@+id/statsSeekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:textColor="@color/gray_100"
android:textSize="16sp"/>
<EditText
android:id="@+id/valueEditText"
android:layout_width="30dp"
android:layout_height="wrap_content"
tools:text="0"
android:gravity="center_horizontal"
android:textColor="@color/gray_100"
style="@style/Body3"
android:textSize="16sp"
android:inputType="number"/>
</merge>

View file

@ -1,4 +1,6 @@
<resources>
<attr name="statsColor" format="color" />
<attr name="statsTitle" format="string" />
<declare-styleable name="AvatarView">
<attr name="showBackground" format="boolean" />
<attr name="showMount" format="boolean" />
@ -50,10 +52,15 @@
</declare-styleable>
<declare-styleable name="StatsView">
<attr name="titleBackgroundColor" format="color" />
<attr name="statsTitle" format="string" />
<attr name="statsColor" format="color" />
<attr name="statsColor" />
<attr name="statsTitle" />
</declare-styleable>
<declare-styleable name="EquipmentItemRow">
<attr name="equipmentTitle" format="string" />
</declare-styleable>
<declare-styleable name="StatsSliderView">
<attr name="statsColor" />
<attr name="statsTextColor" format="color" />
<attr name="statsTitle" />
</declare-styleable>
</resources>

View file

@ -641,10 +641,10 @@
<string name="experience_reward" formatted="false">%d Experience points</string>
<string name="gold_reward" formatted="false">%d Gold</string>
<string name="quest_owner_rewards">Quest Owner Rewards</string>
<string name="str_abbrv">Str:</string>
<string name="per_abbrv">Per:</string>
<string name="int_abbrv">Int:</string>
<string name="con_abbrv">Con:</string>
<string name="str_abbrv">Str</string>
<string name="per_abbrv">Per</string>
<string name="int_abbrv">Int</string>
<string name="con_abbrv">Con</string>
<string name="reset_account">Reset Account</string>
<string name="reset_account_description">WARNING! This resets many parts of your account. This is highly discouraged, but some people find it useful in the beginning after playing with the site for a short time.\n\nYou will lose all your levels, gold, and experience points. All your tasks (except those from challenges) will be deleted permanently and you will lose all of their historical data. You will lose all your equipment but you will be able to buy it all back, including all limited edition equipment or subscriber Mystery items that you already own (you will need to be in the correct class to re-buy class-specific gear). You will keep your current class and your pets and mounts. You might prefer to use an Orb of Rebirth instead, which is a much safer option and which will preserve your tasks and equipment.</string>
<string name="delete_account">Delete Account</string>

View file

@ -87,6 +87,7 @@ import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragme
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyMemberListFragment;
import com.habitrpg.android.habitica.ui.fragments.tasks.TaskRecyclerViewFragment;
import com.habitrpg.android.habitica.ui.fragments.tasks.TasksFragment;
import com.habitrpg.android.habitica.ui.views.BulkAllocateStatsDialog;
import com.habitrpg.android.habitica.ui.views.shops.PurchaseDialog;
import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog;
import com.habitrpg.android.habitica.widget.AvatarStatsWidgetProvider;
@ -290,4 +291,6 @@ public interface AppComponent {
void inject(@NotNull APIPreferenceFragment apiPreferenceFragment);
void inject(@NotNull StatsFragment statsFragment);
void inject(@NotNull BulkAllocateStatsDialog bulkAllocateStatsDialog);
}

View file

@ -0,0 +1,8 @@
package com.habitrpg.android.habitica.extensions
import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
fun AttributeSet.styledAttributes(context: Context?, style: IntArray?): TypedArray? =
context?.theme?.obtainStyledAttributes(this, style, 0, 0)

View file

@ -55,9 +55,9 @@ open class Task : RealmObject, Parcelable {
// used for buyable items
var specialTag: String = ""
@Ignore
var parsedText: CharSequence = ""
var parsedText: CharSequence? = null
@Ignore
var parsedNotes: CharSequence = ""
var parsedNotes: CharSequence? = null
@PrimaryKey
@SerializedName("_id")
var id: String = ""

View file

@ -43,9 +43,9 @@ public class Stats extends RealmObject {
private String userId;
User user;
public Float con, str, per;
public Integer con, str, per;
@SerializedName("int")
public Float _int;
public Integer _int;
public Training training;
public Buffs buffs;
public Integer points, lvl;
@ -179,19 +179,19 @@ public class Stats extends RealmObject {
return buffs;
}
public Float getStr() {
public Integer getStr() {
return str;
}
public Float get_int() {
public Integer get_int() {
return _int;
}
public Float getCon() {
public Integer getCon() {
return con;
}
public Float getPer() {
public Integer getPer() {
return per;
}

View file

@ -6,6 +6,7 @@ import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.InventoryRepository
@ -16,6 +17,7 @@ import com.habitrpg.android.habitica.helpers.UserStatComputer
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.extensions.setScaledPadding
import com.habitrpg.android.habitica.ui.views.BulkAllocateStatsDialog
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import kotlinx.android.synthetic.main.fragment_stats.*
import rx.functions.Action1
@ -111,6 +113,17 @@ class StatsFragment: BaseMainFragment() {
distributeEvenlyHelpButton.setOnClickListener { showHelpAlert(R.string.distribute_evenly_help) }
distributeClassHelpButton.setOnClickListener { showHelpAlert(R.string.distribute_class_help) }
distributeTaskHelpButton.setOnClickListener { showHelpAlert(R.string.distribute_task_help) }
statsAllocationButton.setOnClickListener {
if (user?.stats?.points ?: 0 > 0) {
showBulkAllocateDialog()
}
}
}
private fun showBulkAllocateDialog() {
val dialog = BulkAllocateStatsDialog(context, HabiticaBaseApplication.getComponent())
dialog.show()
}
private fun changeAutoAllocationMode(@Stats.AutoAllocationTypes allocationMode: String) {

View file

@ -34,7 +34,7 @@ import rx.schedulers.Schedulers;
public abstract class ChecklistedViewHolder extends BaseTaskViewHolder implements CompoundButton.OnCheckedChangeListener {
static Integer expandedChecklistRow = null;
private static Integer expandedChecklistRow = null;
@BindView(R.id.checkBoxHolder)
ViewGroup checkboxHolder;
@ -93,13 +93,13 @@ public abstract class ChecklistedViewHolder extends BaseTaskViewHolder implement
public void updateChecklistDisplay() {
//This needs to be a LinearLayout, as ListViews can not be inside other ListViews.
if (this.checklistView != null) {
if (this.shouldDisplayExpandedChecklist() && this.task.getChecklist() != null) {
if (this.shouldDisplayExpandedChecklist()) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (this.task.getChecklist().isValid()) {
for (ChecklistItem item : this.task.getChecklist()) {
LinearLayout itemView = (LinearLayout) layoutInflater.inflate(R.layout.checklist_item_row, this.checklistView, false);
CheckBox checkbox = (CheckBox) itemView.findViewById(R.id.checkBox);
EmojiTextView textView = (EmojiTextView) itemView.findViewById(R.id.checkedTextView);
CheckBox checkbox = itemView.findViewById(R.id.checkBox);
EmojiTextView textView = itemView.findViewById(R.id.checkedTextView);
// Populate the data into the template view using the data object
textView.setText(item.getText());

View file

@ -0,0 +1,103 @@
package com.habitrpg.android.habitica.ui.views
import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.User
import kotlinx.android.synthetic.main.dialog_bulk_allocate.*
import rx.Subscription
import rx.functions.Action1
import javax.inject.Inject
class BulkAllocateStatsDialog(context: Context?, component: AppComponent) : AlertDialog(context) {
@Inject
lateinit var userRepository: UserRepository
var subscription: Subscription? = null
private var allocatedPoints: Int
get() {
var value = 0
value += strengthSliderView.currentValue
value += intelligenceSliderView.currentValue
value += constitutionSliderView.currentValue
value += perceptionSliderView.currentValue
return value
}
set(value) {
return
}
private var pointsToAllocate = 0
set(value) {
field = value
updateTitle()
strengthSliderView.maxValue = pointsToAllocate
intelligenceSliderView.maxValue = pointsToAllocate
constitutionSliderView.maxValue = pointsToAllocate
perceptionSliderView.maxValue = pointsToAllocate
}
private var user: User? = null
set(value) {
field = value
pointsToAllocate = user?.stats?.points ?: 0
strengthSliderView.previousValue = user?.stats?.str ?: 0
intelligenceSliderView.previousValue = user?.stats?._int ?: 0
constitutionSliderView.previousValue = user?.stats?.con ?: 0
perceptionSliderView.previousValue = user?.stats?.per ?: 0
}
init {
component.inject(this)
val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.dialog_bulk_allocate, null)
setView(view)
this.setButton(android.support.v7.app.AlertDialog.BUTTON_POSITIVE, context?.getString(R.string.done)) { _, _ ->
this.dismiss()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
subscription = userRepository.user.subscribe(Action1 {
user = it
}, RxErrorHandler.handleEmptyError())
strengthSliderView.allocateAction = {
updateTitle()
}
intelligenceSliderView.allocateAction = {
updateTitle()
}
constitutionSliderView.allocateAction = {
updateTitle()
}
perceptionSliderView.allocateAction = {
updateTitle()
}
}
override fun dismiss() {
subscription?.unsubscribe()
super.dismiss()
}
private fun updateTitle() {
allocatedTitle.text = allocatedPoints.toString() + "/" + pointsToAllocate.toString()
if (allocatedPoints > 0) {
titleView.setBackgroundColor(ContextCompat.getColor(context, R.color.brand_400))
} else {
titleView.setBackgroundColor(ContextCompat.getColor(context, R.color.gray_400))
}
}
}

View file

@ -0,0 +1,70 @@
package com.habitrpg.android.habitica.ui.views
import android.content.Context
import android.graphics.PorterDuff
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import android.widget.SeekBar
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.styledAttributes
import kotlinx.android.synthetic.main.stats_slider_view.view.*
class StatsSliderView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
var previousValue = 0
set(value) {
field = value
previousValueTextView.text = value.toString()
}
var maxValue = 0
set(value) {
field = value
statsSeekBar.max = field
}
var currentValue = 0
set(value) {
field = value
statsSeekBar.progress = value
valueEditText.setText(value.toString())
}
var allocateAction: ((Int) -> Unit)? = null
init {
View.inflate(context, R.layout.stats_slider_view, this)
gravity = Gravity.CENTER_VERTICAL
val attributes = attrs?.styledAttributes(context, R.styleable.StatsSliderView)
if (attributes != null) {
statTypeTitle.text = attributes.getString(R.styleable.StatsSliderView_statsTitle)
val statColor = attributes.getColor(R.styleable.StatsSliderView_statsColor, 0)
statTypeTitle.setTextColor(attributes.getColor(R.styleable.StatsSliderView_statsTextColor, 0))
statsSeekBar.progressDrawable.setColorFilter(statColor, PorterDuff.Mode.MULTIPLY)
statsSeekBar.thumb.setColorFilter(statColor, PorterDuff.Mode.MULTIPLY)
}
statsSeekBar.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
currentValue = progress
if (fromUser) {
allocateAction?.invoke(currentValue)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
currentValue = 0
}
}