Numerical habits: allow Tasker to increment/decrement value

pull/630/head
Alinson S. Xavier 5 years ago
parent 07f8583c3d
commit 61f32449dd

@ -22,8 +22,7 @@ package org.isoron.uhabits.automation
import android.app.* import android.app.*
import android.content.* import android.content.*
import android.os.* import android.os.*
import org.isoron.uhabits.* import org.isoron.uhabits.R
import org.isoron.uhabits.automation.FireSettingReceiver.*
import org.isoron.uhabits.core.models.* import org.isoron.uhabits.core.models.*
class EditSettingController(private val activity: Activity) { class EditSettingController(private val activity: Activity) {
@ -45,11 +44,13 @@ class EditSettingController(private val activity: Activity) {
} }
private fun getActionName(action: Int): String { private fun getActionName(action: Int): String {
when (action) { return when (action) {
ACTION_CHECK -> return activity.getString(R.string.check) ACTION_CHECK -> activity.getString(R.string.check)
ACTION_UNCHECK -> return activity.getString(R.string.uncheck) ACTION_UNCHECK -> activity.getString(R.string.uncheck)
ACTION_TOGGLE -> return activity.getString(R.string.toggle) ACTION_TOGGLE -> activity.getString(R.string.toggle)
else -> return "???" ACTION_INCREMENT -> activity.getString(R.string.increment)
ACTION_DECREMENT -> activity.getString(R.string.decrement)
else -> "???"
} }
} }
} }

@ -21,6 +21,7 @@ package org.isoron.uhabits.automation
import android.R.layout.* import android.R.layout.*
import android.content.* import android.content.*
import android.view.*
import androidx.appcompat.widget.* import androidx.appcompat.widget.*
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.widget.* import android.widget.*
@ -51,10 +52,17 @@ class EditSettingRootView(
addView(inflate(getContext(), R.layout.automation, null)) addView(inflate(getContext(), R.layout.automation, null))
ButterKnife.bind(this) ButterKnife.bind(this)
populateHabitSpinner() populateHabitSpinner()
habitSpinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
populateActionSpinner(habitList.getByPosition(position).isNumerical)
}
}
args?.let { args?.let {
habitSpinner.setSelection(habitList.indexOf(it.habit)) habitSpinner.setSelection(habitList.indexOf(it.habit))
actionSpinner.setSelection(it.action) populateActionSpinner(it.habit.isNumerical)
actionSpinner.setSelection(mapActionToSpinnerPosition(it.action))
} }
} }
@ -72,16 +80,49 @@ class EditSettingRootView(
@OnClick(R.id.buttonSave) @OnClick(R.id.buttonSave)
fun onClickSave() { fun onClickSave() {
val action = actionSpinner.selectedItemPosition val habit = habitList.getByPosition(habitSpinner.selectedItemPosition)
val habitPosition = habitSpinner.selectedItemPosition val action = mapSpinnerPositionToAction(habit.isNumerical,
val habit = habitList.getByPosition(habitPosition) actionSpinner.selectedItemPosition)
controller.onSave(habit, action) controller.onSave(habit, action)
} }
private fun mapSpinnerPositionToAction(isNumerical: Boolean, itemPosition: Int): Int {
return if (isNumerical) {
when (itemPosition) {
0 -> ACTION_INCREMENT
else -> ACTION_DECREMENT
}
} else {
when (itemPosition) {
0 -> ACTION_CHECK
1 -> ACTION_UNCHECK
else -> ACTION_TOGGLE
}
}
}
private fun mapActionToSpinnerPosition(action: Int): Int {
return when(action) {
ACTION_CHECK -> 0
ACTION_UNCHECK -> 1
ACTION_TOGGLE -> 2
ACTION_INCREMENT -> 0
ACTION_DECREMENT -> 1
else -> 0
}
}
private fun populateHabitSpinner() { private fun populateHabitSpinner() {
val names = habitList.mapTo(LinkedList<String>()) { it.name } val names = habitList.mapTo(LinkedList()) { it.name }
val adapter = ArrayAdapter(context, simple_spinner_item, names) val adapter = ArrayAdapter(context, simple_spinner_item, names)
adapter.setDropDownViewResource(simple_spinner_dropdown_item) adapter.setDropDownViewResource(simple_spinner_dropdown_item)
habitSpinner.adapter = adapter habitSpinner.adapter = adapter
} }
private fun populateActionSpinner(isNumerical: Boolean) {
val entries = (if (isNumerical) R.array.actions_numerical else R.array.actions_yes_no)
val adapter = ArrayAdapter.createFromResource(context, entries, simple_spinner_item)
adapter.setDropDownViewResource(simple_spinner_dropdown_item)
actionSpinner.adapter = adapter
}
} }

@ -30,6 +30,9 @@ import org.isoron.uhabits.receivers.*
const val ACTION_CHECK = 0 const val ACTION_CHECK = 0
const val ACTION_UNCHECK = 1 const val ACTION_UNCHECK = 1
const val ACTION_TOGGLE = 2 const val ACTION_TOGGLE = 2
const val ACTION_INCREMENT = 3
const val ACTION_DECREMENT = 4
const val EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE" const val EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE"
const val EXTRA_STRING_BLURB = "com.twofortyfouram.locale.intent.extra.BLURB" const val EXTRA_STRING_BLURB = "com.twofortyfouram.locale.intent.extra.BLURB"
@ -52,11 +55,13 @@ class FireSettingReceiver : BroadcastReceiver() {
ACTION_CHECK -> controller.onAddRepetition(args.habit, timestamp) ACTION_CHECK -> controller.onAddRepetition(args.habit, timestamp)
ACTION_UNCHECK -> controller.onRemoveRepetition(args.habit, timestamp) ACTION_UNCHECK -> controller.onRemoveRepetition(args.habit, timestamp)
ACTION_TOGGLE -> controller.onToggleRepetition(args.habit, timestamp) ACTION_TOGGLE -> controller.onToggleRepetition(args.habit, timestamp)
ACTION_INCREMENT -> controller.onIncrement(args.habit, timestamp, 1000)
ACTION_DECREMENT -> controller.onDecrement(args.habit, timestamp, 1000)
} }
} }
@ReceiverScope @ReceiverScope
@Component(dependencies = arrayOf(HabitsApplicationComponent::class)) @Component(dependencies = [HabitsApplicationComponent::class])
internal interface ReceiverComponent { internal interface ReceiverComponent {
val widgetController: WidgetBehavior val widgetController: WidgetBehavior
} }

@ -9,7 +9,7 @@ object SettingUtils {
fun parseIntent(intent: Intent, allHabits: HabitList): Arguments? { fun parseIntent(intent: Intent, allHabits: HabitList): Arguments? {
val bundle = intent.getBundleExtra(EXTRA_BUNDLE) ?: return null val bundle = intent.getBundleExtra(EXTRA_BUNDLE) ?: return null
val action = bundle.getInt("action") val action = bundle.getInt("action")
if (action < 0 || action > 2) return null if (action < 0 || action > 4) return null
val habit = allHabits.getById(bundle.getLong("habit")) ?: return null val habit = allHabits.getById(bundle.getLong("habit")) ?: return null
return Arguments(action, habit) return Arguments(action, habit)
} }

@ -22,67 +22,81 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical"
android:background="@color/white">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
style="@style/Toolbar" android:layout_width="match_parent"
android:title="@string/app_name" android:layout_height="wrap_content"
app:popupTheme="?toolbarPopupTheme"/> android:background="?attr/colorPrimary"
android:elevation="2dp"
android:gravity="end"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:title="@string/app_name"
app:titleTextColor="@color/white">
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonSave"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="16dp"
android:text="@string/save"
android:textColor="@color/white"
app:rippleColor="@color/white"
app:strokeColor="@color/white" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout <LinearLayout
android:id="@+id/formPanel" android:id="@+id/formPanel"
style="@style/dialogFormPanel"> style="@style/dialogFormPanel">
<LinearLayout <FrameLayout style="@style/FormOuterBox">
style="@style/dialogFormRow"> <LinearLayout style="@style/FormInnerBox">
<TextView <TextView
style="@style/dialogFormLabel" style="@style/FormLabel"
android:text="@string/action"/> android:text="@string/habit" />
<androidx.appcompat.widget.AppCompatSpinner <androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/actionSpinner" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="25dp" android:paddingTop="16dp"
android:entries="@array/actions" android:paddingBottom="16dp"
android:minWidth="400dp" android:paddingLeft="8dp"
android:theme="@style/dialogFormText"/> android:paddingRight="8dp"
android:id="@+id/habitSpinner"
android:text="@string/check" />
</LinearLayout> </LinearLayout>
</FrameLayout>
<LinearLayout <FrameLayout style="@style/FormOuterBox">
style="@style/dialogFormRow"> <LinearLayout style="@style/FormInnerBox">
<TextView <TextView
style="@style/dialogFormLabel" style="@style/FormLabel"
android:text="@string/habit"/> android:text="@string/action" />
<androidx.appcompat.widget.AppCompatSpinner <androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/habitSpinner"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:entries="@array/actions"
android:minWidth="400dp"
android:theme="@style/dialogFormText"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:layout_width="match_parent"
android:paddingEnd="16dp" android:id="@+id/actionSpinner"
android:paddingLeft="0dp" android:entries="@array/actions_yes_no"
android:paddingRight="16dp" android:paddingTop="16dp"
android:paddingStart="0dp"> android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/check" />
</LinearLayout>
</FrameLayout>
<Button
android:id="@+id/buttonSave"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

@ -72,12 +72,17 @@
<item>-1</item> <item>-1</item>
</integer-array> </integer-array>
<string-array name="actions" translatable="false"> <string-array name="actions_yes_no" translatable="false">
<item>@string/check</item> <item>@string/check</item>
<item>@string/uncheck</item> <item>@string/uncheck</item>
<item>@string/toggle</item> <item>@string/toggle</item>
</string-array> </string-array>
<string-array name="actions_numerical" translatable="false">
<item>@string/increment</item>
<item>@string/decrement</item>
</string-array>
<string-array name="strengthIntervalNames" translatable="false"> <string-array name="strengthIntervalNames" translatable="false">
<item>@string/day</item> <item>@string/day</item>
<item>@string/week</item> <item>@string/week</item>

@ -198,4 +198,6 @@
<string name="no_habits">No habits found</string> <string name="no_habits">No habits found</string>
<string name="no_numerical_habits">No measurable habits found</string> <string name="no_numerical_habits">No measurable habits found</string>
<string name="no_boolean_habits">No yes-or-no habits found</string> <string name="no_boolean_habits">No yes-or-no habits found</string>
<string name="increment">Increment</string>
<string name="decrement">Decrement</string>
</resources> </resources>

@ -24,6 +24,7 @@ import androidx.annotation.*;
import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.commands.*;
import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.ui.*; import org.isoron.uhabits.core.ui.*;
import org.jetbrains.annotations.*;
import javax.inject.*; import javax.inject.*;
@ -82,4 +83,13 @@ public class WidgetBehavior
habit.getId()); habit.getId());
} }
public void onIncrement(@NotNull Habit habit, @NotNull Timestamp timestamp, int amount) {
int currentValue = habit.getCheckmarks().getValues(timestamp, timestamp)[0];
setNumericValue(habit, timestamp, currentValue + amount);
}
public void onDecrement(@NotNull Habit habit, @NotNull Timestamp timestamp, int amount) {
int currentValue = habit.getCheckmarks().getValues(timestamp, timestamp)[0];
setNumericValue(habit, timestamp, currentValue - amount);
}
} }

Loading…
Cancel
Save