mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-20 04:39:04 +00:00
begin implementing bulk allocation
This commit is contained in:
parent
4d11bcf172
commit
0732b0500e
13 changed files with 344 additions and 18 deletions
69
Habitica/res/layout/dialog_bulk_allocate.xml
Normal file
69
Habitica/res/layout/dialog_bulk_allocate.xml
Normal 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>
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
52
Habitica/res/layout/stats_slider_view.xml
Normal file
52
Habitica/res/layout/stats_slider_view.xml
Normal 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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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 = ""
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue