Update checkmark widget for numerical support

Co-authored-by: Alinson S. Xavier <git@axavier.org>
pull/605/head
Thomas S 5 years ago committed by Alinson S. Xavier
parent a8e77b8df8
commit 96d23bdf22

@ -53,6 +53,7 @@ public class CheckmarkWidgetViewTest extends BaseViewTest
float percentage = (float) score;
view.setActiveColor(PaletteUtils.getAndroidTestColor(0));
view.setCheckmarkState(habit.getCheckmarks().getTodayValue());
view.setCheckmarkValue(habit.getCheckmarks().getTodayValue());
view.setPercentage(percentage);
view.setName(habit.getName());

@ -84,7 +84,17 @@
</activity>
<activity
android:name=".notifications.SnoozeDelayPickerActivity"
android:name=".widgets.activities.NumericalCheckmarkWidgetActivity"
android:label="NumericalCheckmarkWidget"
android:noHistory="true"
android:excludeFromRecents="true"
android:theme="@style/Theme.AppCompat.Light.Dialog">
<intent-filter>
<action android:name="org.isoron.uhabits.ACTION_SHOW_NUMERICAL_VALUE_ACTIVITY"/>
</intent-filter>
</activity>
<activity android:name=".notifications.SnoozeDelayPickerActivity"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
@ -174,7 +184,14 @@
<receiver android:name=".receivers.WidgetReceiver">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="org.isoron.uhabits.ACTION_SET_NUMERICAL_VALUE"/>
<data
android:host="org.isoron.uhabits"
android:scheme="content"/>
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION" />

@ -69,6 +69,9 @@ class NumberPickerFactory
val v = picker.value + 0.05 * picker2.value
callback.onNumberPicked(v)
}
.setOnDismissListener{
callback.onNumberPickerDismissed()
}
.create()
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)

@ -36,6 +36,11 @@ class IntentParser
return CheckmarkIntentData(parseHabit(uri), parseTimestamp(intent))
}
fun copyIntentData(source: Intent, destination: Intent) {
destination.data = source.data;
destination.putExtra("timestamp", source.getLongExtra("timestamp", DateUtils.getToday().unixTime))
}
private fun parseHabit(uri: Uri): Habit {
val habit = habits.getById(parseId(uri)) ?:
throw IllegalArgumentException("habit not found")

@ -103,4 +103,19 @@ class PendingIntentFactory
if (timestamp != null) putExtra("timestamp", timestamp)
},
FLAG_UPDATE_CURRENT)
fun setNumericalValue(widgetContext: Context,
habit: Habit,
numericalValue: Int,
timestamp: Long?):
PendingIntent =
getBroadcast(
widgetContext, 2,
Intent(widgetContext, WidgetReceiver::class.java).apply {
data = Uri.parse(habit.uriString)
action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE
putExtra("numericalValue", numericalValue);
if (timestamp != null) putExtra("timestamp", timestamp)
},
FLAG_UPDATE_CURRENT)
}

@ -27,6 +27,7 @@ import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.ui.widgets.*;
import org.isoron.uhabits.intents.*;
import org.isoron.uhabits.sync.*;
import org.isoron.uhabits.widgets.activities.*;
import dagger.*;
@ -49,6 +50,9 @@ public class WidgetReceiver extends BroadcastReceiver
public static final String ACTION_TOGGLE_REPETITION =
"org.isoron.uhabits.ACTION_TOGGLE_REPETITION";
public static final String ACTION_SET_NUMERICAL_VALUE =
"org.isoron.uhabits.ACTION_SET_NUMERICAL_VALUE";
private static final String TAG = "WidgetReceiver";
@Override
@ -104,6 +108,14 @@ public class WidgetReceiver extends BroadcastReceiver
controller.onRemoveRepetition(data.getHabit(),
data.getTimestamp());
break;
case ACTION_SET_NUMERICAL_VALUE:
Intent numberSelectorIntent = new Intent(context, NumericalCheckmarkWidgetActivity.class);
numberSelectorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
numberSelectorIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
numberSelectorIntent.setAction(NumericalCheckmarkWidgetActivity.ACTION_SHOW_NUMERICAL_VALUE_ACTIVITY);
parser.copyIntentData(intent,numberSelectorIntent);
context.startActivity(numberSelectorIntent);
break;
}
}
catch (RuntimeException e)

@ -19,33 +19,58 @@
package org.isoron.uhabits.widgets
import android.app.*
import android.content.*
import android.view.*
import org.isoron.uhabits.core.models.*
import org.isoron.uhabits.utils.*
import org.isoron.uhabits.widgets.views.*
class CheckmarkWidget(
open class CheckmarkWidget(
context: Context,
widgetId: Int,
private val habit: Habit
protected val habit: Habit
) : BaseWidget(context, widgetId) {
override fun getOnClickPendingIntent(context: Context) =
override fun getOnClickPendingIntent(context: Context): PendingIntent {
return if (habit.isNumerical) {
pendingIntentFactory.setNumericalValue(context, habit, 10, null)
} else {
pendingIntentFactory.toggleCheckmark(habit, null)
}
}
override fun refreshData(v: View) {
(v as CheckmarkWidgetView).apply {
setBackgroundAlpha(preferedBackgroundAlpha)
setPercentage(habit.scores.todayValue.toFloat())
setActiveColor(PaletteUtils.getColor(context, habit.color))
setName(habit.name)
setCheckmarkValue(habit.checkmarks.todayValue)
if (habit.isNumerical) {
setNumerical(true)
setCheckmarkState(getNumericalCheckmarkState())
} else {
setCheckmarkState(habit.checkmarks.todayValue)
}
setPercentage(habit.scores.todayValue.toFloat())
refresh()
}
}
override fun buildView() = CheckmarkWidgetView(context)
override fun buildView(): View {
return CheckmarkWidgetView(context)
}
override fun getDefaultHeight() = 125
override fun getDefaultWidth() = 125
private fun getNumericalCheckmarkState(): Int {
return if (habit.isCompletedToday) {
Checkmark.CHECKED_EXPLICITLY
} else {
Checkmark.UNCHECKED
}
}
}

@ -0,0 +1,76 @@
/*
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.widgets.activities
import android.app.*
import android.content.*
import android.os.*
import android.view.*
import android.widget.FrameLayout
import org.isoron.uhabits.*
import org.isoron.uhabits.activities.*
import org.isoron.uhabits.activities.common.dialogs.*
import org.isoron.uhabits.core.ui.screens.habits.list.*
import org.isoron.uhabits.core.ui.widgets.*
import org.isoron.uhabits.intents.*
import org.isoron.uhabits.widgets.*
class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPickerCallback {
private lateinit var behavior: WidgetBehavior
private lateinit var data: IntentParser.CheckmarkIntentData
private lateinit var widgetUpdater: WidgetUpdater
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(FrameLayout(this))
val app = this.applicationContext as HabitsApplication
val component = app.component
val parser = app.component.intentParser
data = parser.parseCheckmarkIntent(intent)
behavior = WidgetBehavior(component.habitList, component.commandRunner, component.notificationTray)
widgetUpdater = component.widgetUpdater
showNumberSelector(this)
}
override fun onNumberPicked(newValue: Double) {
behavior.setNumericValue(data.habit, data.timestamp, (newValue * 1000).toInt())
widgetUpdater.updateWidgets()
finish()
}
override fun onNumberPickerDismissed() {
finish()
}
private fun showNumberSelector(context: Context) {
val app = this.applicationContext as HabitsApplication
AndroidThemeSwitcher(this, app.component.preferences).apply()
val numberPickerFactory = NumberPickerFactory(context)
numberPickerFactory.create(data.habit.checkmarks.today!!.value.toDouble() / 1000,
data.habit.unit,
this).show()
}
companion object {
const val ACTION_SHOW_NUMERICAL_VALUE_ACTIVITY = "org.isoron.uhabits.ACTION_SHOW_NUMERICAL_VALUE_ACTIVITY"
}
}

@ -28,26 +28,30 @@ import androidx.annotation.Nullable;
import org.isoron.androidbase.utils.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.habits.list.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.utils.*;
import static org.isoron.androidbase.utils.InterfaceUtils.getDimension;
public class CheckmarkWidgetView extends HabitWidgetView
{
private int activeColor;
public class CheckmarkWidgetView extends HabitWidgetView {
protected int activeColor;
private float percentage;
protected float percentage;
@Nullable
private String name;
protected String name;
private RingView ring;
protected RingView ring;
private TextView label;
protected TextView label;
private int checkmarkValue;
protected int checkmarkValue;
protected int checkmarkState;
protected boolean isNumerical;
public CheckmarkWidgetView(Context context)
{
@ -67,14 +71,11 @@ public class CheckmarkWidgetView extends HabitWidgetView
StyledResources res = new StyledResources(getContext());
String text;
int bgColor;
int fgColor;
switch (checkmarkValue)
{
switch (checkmarkState) {
case Checkmark.CHECKED_EXPLICITLY:
text = getResources().getString(R.string.fa_check);
bgColor = activeColor;
fgColor = res.getColor(R.attr.highContrastReverseTextColor);
setShadowAlpha(0x4f);
@ -83,15 +84,9 @@ public class CheckmarkWidgetView extends HabitWidgetView
break;
case Checkmark.CHECKED_IMPLICITLY:
text = getResources().getString(R.string.fa_check);
bgColor = res.getColor(R.attr.cardBgColor);
fgColor = res.getColor(R.attr.mediumContrastTextColor);
setShadowAlpha(0x00);
break;
case Checkmark.UNCHECKED:
default:
text = getResources().getString(R.string.fa_times);
getResources().getString(R.string.fa_times);
bgColor = res.getColor(R.attr.cardBgColor);
fgColor = res.getColor(R.attr.mediumContrastTextColor);
setShadowAlpha(0x00);
@ -101,7 +96,7 @@ public class CheckmarkWidgetView extends HabitWidgetView
ring.setPercentage(percentage);
ring.setColor(fgColor);
ring.setBackgroundColor(bgColor);
ring.setText(text);
ring.setText(getText());
label.setText(name);
label.setTextColor(fgColor);
@ -110,6 +105,25 @@ public class CheckmarkWidgetView extends HabitWidgetView
postInvalidate();
}
public void setCheckmarkState(int checkmarkState)
{
this.checkmarkState = checkmarkState;
}
protected String getText()
{
if (isNumerical) return NumberButtonViewKt.toShortString(checkmarkValue / 1000.0);
switch (checkmarkState) {
case Checkmark.CHECKED_EXPLICITLY:
case Checkmark.CHECKED_IMPLICITLY:
return getResources().getString(R.string.fa_check);
case Checkmark.UNCHECKED:
default:
return getResources().getString(R.string.fa_times);
}
}
public void setActiveColor(int activeColor)
{
this.activeColor = activeColor;
@ -130,6 +144,11 @@ public class CheckmarkWidgetView extends HabitWidgetView
this.percentage = percentage;
}
public void setNumerical(boolean isNumerical)
{
this.isNumerical = isNumerical;
}
@Override
@NonNull
protected Integer getInnerLayoutId()

@ -327,9 +327,9 @@ public class Habit
if (isNumerical())
{
if(getTargetType() == AT_LEAST)
return todayCheckmark >= data.targetValue;
return todayCheckmark / 1000.0 >= data.targetValue;
else
return todayCheckmark <= data.targetValue;
return todayCheckmark / 1000.0 <= data.targetValue;
}
else return (todayCheckmark != UNCHECKED);
}

@ -177,6 +177,8 @@ public class ListHabitsBehavior
public interface NumberPickerCallback
{
void onNumberPicked(double newValue);
default void onNumberPickerDismissed() {}
}
public interface Screen

@ -73,4 +73,11 @@ public class WidgetBehavior
new ToggleRepetitionCommand(habitList, habit, timestamp),
habit.getId());
}
public void setNumericValue(@NonNull Habit habit, Timestamp timestamp, int newValue) {
commandRunner.execute(
new CreateRepetitionCommand(habit, timestamp, newValue),
habit.getId());
}
}

@ -102,19 +102,19 @@ public class HabitTest extends BaseUnitTest
h.setTargetValue(100.0);
assertFalse(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 200);
h.getRepetitions().toggle(getToday(), 200_000);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 100);
h.getRepetitions().toggle(getToday(), 100_000);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 50);
h.getRepetitions().toggle(getToday(), 50_000);
assertFalse(h.isCompletedToday());
h.setTargetType(Habit.AT_MOST);
h.getRepetitions().toggle(getToday(), 200);
h.getRepetitions().toggle(getToday(), 200_000);
assertFalse(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 100);
h.getRepetitions().toggle(getToday(), 100_000);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 50);
h.getRepetitions().toggle(getToday(), 50_000);
assertTrue(h.isCompletedToday());
}

Loading…
Cancel
Save