mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Numerical habits: allow Tasker to increment/decrement value
This commit is contained in:
@@ -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">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/toolbar"
|
android:layout_width="match_parent"
|
||||||
style="@style/Toolbar"
|
android:layout_height="wrap_content">
|
||||||
android:title="@string/app_name"
|
|
||||||
app:popupTheme="?toolbarPopupTheme"/>
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
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
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/habit" />
|
||||||
|
|
||||||
<TextView
|
<androidx.appcompat.widget.AppCompatSpinner
|
||||||
style="@style/dialogFormLabel"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/action"/>
|
android:layout_width="match_parent"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:id="@+id/habitSpinner"
|
||||||
|
android:text="@string/check" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSpinner
|
<FrameLayout style="@style/FormOuterBox">
|
||||||
android:id="@+id/actionSpinner"
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
android:layout_width="wrap_content"
|
<TextView
|
||||||
android:layout_height="25dp"
|
style="@style/FormLabel"
|
||||||
android:entries="@array/actions"
|
android:text="@string/action" />
|
||||||
android:minWidth="400dp"
|
|
||||||
android:theme="@style/dialogFormText"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.appcompat.widget.AppCompatSpinner
|
||||||
style="@style/dialogFormRow">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/actionSpinner"
|
||||||
|
android:entries="@array/actions_yes_no"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:text="@string/check" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/dialogFormLabel"
|
|
||||||
android:text="@string/habit"/>
|
|
||||||
|
|
||||||
<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:gravity="end"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingLeft="0dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:paddingStart="0dp">
|
|
||||||
|
|
||||||
<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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user