diff --git a/android/uhabits-android/src/main/AndroidManifest.xml b/android/uhabits-android/src/main/AndroidManifest.xml
index 13d637217..904b5bb9c 100644
--- a/android/uhabits-android/src/main/AndroidManifest.xml
+++ b/android/uhabits-android/src/main/AndroidManifest.xml
@@ -136,6 +136,18 @@
android:resource="@xml/widget_checkmark_info" />
+
+
+
+
+
+
+
+
+ *
+ * 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 .
+ */
+
+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.*
+
+open class CheckmarkWidgetWithTime(
+ context: Context,
+ widgetId: Int,
+ protected val habit: Habit
+) : BaseWidget(context, widgetId) {
+
+ 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 CheckmarkTimeWidgetView).apply {
+ setBackgroundAlpha(preferedBackgroundAlpha)
+
+ 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(): View {
+ return CheckmarkTimeWidgetView(context)
+ }
+
+ override fun getDefaultHeight() = 125
+ override fun getDefaultWidth() = 125
+
+ private fun getNumericalCheckmarkState(): Int {
+ return if (habit.isCompletedToday) {
+ Checkmark.CHECKED_EXPLICITLY
+ } else {
+ Checkmark.UNCHECKED
+ }
+ }
+
+}
diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt
new file mode 100644
index 000000000..69955a6ca
--- /dev/null
+++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidgetWithTimeProvider.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 Álinson Santos Xavier
+ *
+ * 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 .
+ */
+package org.isoron.uhabits.widgets
+
+import android.content.*
+
+class CheckmarkWidgetWithTimeProvider : BaseWidgetProvider() {
+ override fun getWidgetFromId(context: Context, id: Int): BaseWidget {
+ val habits = getHabitsFromWidgetId(id)
+ if (habits.size == 1) return CheckmarkWidgetWithTime(context, id, habits[0])
+ else return StackWidget(context, id, StackWidgetType.CHECKMARKTIME, habits)
+ }
+}
diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java
index 7a014f394..998e8757a 100644
--- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java
+++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java
@@ -2,6 +2,8 @@ package org.isoron.uhabits.widgets;
import org.isoron.uhabits.R;
+import java.lang.annotation.Target;
+
/**
* Created by victoryu on 11/3/17.
*/
@@ -13,7 +15,8 @@ public enum StackWidgetType {
SCORE(2), // habit strength widget
HISTORY(3),
STREAKS(4),
- TARGET(5);
+ TARGET(5),
+ CHECKMARKTIME(6);
private int value;
StackWidgetType(int value) {
@@ -37,6 +40,8 @@ public enum StackWidgetType {
return STREAKS;
} else if (TARGET.getValue() == value) {
return TARGET;
+ } else if (CHECKMARKTIME.getValue() == value) {
+ return CHECKMARKTIME;
}
return null;
}
@@ -55,6 +60,8 @@ public enum StackWidgetType {
return R.layout.streak_stackview_widget;
case TARGET:
return R.layout.target_stackview_widget;
+ case CHECKMARKTIME:
+ return R.layout.checkmarktime_stackview_widget;
}
return 0;
}
@@ -73,6 +80,8 @@ public enum StackWidgetType {
return R.id.streakStackWidgetView;
case TARGET:
return R.id.targetStackWidgetView;
+ case CHECKMARKTIME:
+ return R.id.checkmarkTimeStackWidgetView;
}
return 0;
}
@@ -91,6 +100,8 @@ public enum StackWidgetType {
return R.id.streakStackWidgetEmptyView;
case TARGET:
return R.id.targetStackWidgetEmptyView;
+ case CHECKMARKTIME:
+ return R.id.checkmarkTimeStackWidgetEmptyView;
}
return 0;
}
diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt
index 17d6d5d77..14c383245 100644
--- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt
+++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt
@@ -68,6 +68,7 @@ class WidgetUpdater
updateWidgets(modifiedHabitId, StreakWidgetProvider::class.java)
updateWidgets(modifiedHabitId, FrequencyWidgetProvider::class.java)
updateWidgets(modifiedHabitId, TargetWidgetProvider::class.java)
+ updateWidgets(modifiedHabitId, CheckmarkWidgetWithTimeProvider::class.java)
}
}
diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java
new file mode 100644
index 000000000..a0f32ec82
--- /dev/null
+++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkTimeWidgetView.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2016 Álinson Santos Xavier
+ *
+ * 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 .
+ */
+
+package org.isoron.uhabits.widgets.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.isoron.androidbase.utils.StyledResources;
+import org.isoron.uhabits.R;
+import org.isoron.uhabits.activities.common.views.RingView;
+import org.isoron.uhabits.activities.habits.list.views.NumberButtonViewKt;
+import org.isoron.uhabits.core.models.Checkmark;
+import org.isoron.uhabits.utils.PaletteUtils;
+
+import static org.isoron.androidbase.utils.InterfaceUtils.getDimension;
+
+public class CheckmarkTimeWidgetView extends HabitWidgetView {
+ protected int activeColor;
+
+ protected float percentage;
+
+ @Nullable
+ protected String name;
+
+ protected RingView ring;
+
+ protected TextView label;
+
+ protected int checkmarkValue;
+
+ protected int checkmarkState;
+
+ protected boolean isNumerical;
+
+ public CheckmarkTimeWidgetView(Context context)
+ {
+ super(context);
+ init();
+ }
+
+ public CheckmarkTimeWidgetView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ init();
+ }
+
+ public void refresh()
+ {
+ if (backgroundPaint == null || frame == null || ring == null) return;
+
+ StyledResources res = new StyledResources(getContext());
+
+ int bgColor;
+ int fgColor;
+
+ switch (checkmarkState) {
+ case Checkmark.CHECKED_EXPLICITLY:
+ case Checkmark.SKIPPED:
+ bgColor = activeColor;
+ fgColor = res.getColor(R.attr.highContrastReverseTextColor);
+ setShadowAlpha(0x4f);
+ backgroundPaint.setColor(bgColor);
+ frame.setBackgroundDrawable(background);
+ break;
+
+ case Checkmark.CHECKED_IMPLICITLY:
+ case Checkmark.UNCHECKED:
+ default:
+ getResources().getString(R.string.fa_times);
+ bgColor = res.getColor(R.attr.cardBgColor);
+ fgColor = res.getColor(R.attr.mediumContrastTextColor);
+ setShadowAlpha(0x00);
+ break;
+ }
+
+ ring.setPercentage(percentage);
+ ring.setColor(fgColor);
+ ring.setBackgroundColor(bgColor);
+ ring.setText(getText());
+
+ label.setText(name);
+ label.setTextColor(fgColor);
+
+ requestLayout();
+ 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.SKIPPED:
+ return getResources().getString(R.string.fa_skipped);
+ case Checkmark.UNCHECKED:
+ default:
+ return getResources().getString(R.string.fa_times);
+ }
+ }
+
+ public void setActiveColor(int activeColor)
+ {
+ this.activeColor = activeColor;
+ }
+
+ public void setCheckmarkValue(int checkmarkValue)
+ {
+ this.checkmarkValue = checkmarkValue;
+ }
+
+ public void setName(@NonNull String name)
+ {
+ this.name = name;
+ }
+
+ public void setPercentage(float percentage)
+ {
+ this.percentage = percentage;
+ }
+
+ public void setNumerical(boolean isNumerical)
+ {
+ this.isNumerical = isNumerical;
+ }
+
+ @Override
+ @NonNull
+ protected Integer getInnerLayoutId()
+ {
+ return R.layout.widget_checkmarktime;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ float w = width;
+ float h = width * 1.25f;
+ float scale = Math.min(width / w, height / h);
+
+ w *= scale;
+ h *= scale;
+
+ if (h < getDimension(getContext(), R.dimen.checkmarkWidget_heightBreakpoint))
+ ring.setVisibility(GONE);
+ else
+ ring.setVisibility(VISIBLE);
+
+ widthMeasureSpec =
+ MeasureSpec.makeMeasureSpec((int) w, MeasureSpec.EXACTLY);
+ heightMeasureSpec =
+ MeasureSpec.makeMeasureSpec((int) h, MeasureSpec.EXACTLY);
+
+ float textSize = 0.15f * h;
+ float maxTextSize = getDimension(getContext(), R.dimen.smallerTextSize);
+ textSize = Math.min(textSize, maxTextSize);
+
+ label.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+ ring.setTextSize(textSize);
+ ring.setThickness(0.15f * textSize);
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ private void init()
+ {
+ ring = (RingView) findViewById(R.id.scoreRing);
+ label = (TextView) findViewById(R.id.label);
+
+ if (ring != null) ring.setIsTransparencyEnabled(true);
+
+ if (isInEditMode())
+ {
+ percentage = 0.75f;
+ name = "Wake up early";
+ activeColor = PaletteUtils.getAndroidTestColor(6);
+ checkmarkValue = Checkmark.CHECKED_EXPLICITLY;
+ refresh();
+ }
+ }
+}
diff --git a/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml b/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml
new file mode 100644
index 000000000..9547321b4
--- /dev/null
+++ b/android/uhabits-android/src/main/res/layout/checkmarktime_stackview_widget.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml b/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml
new file mode 100644
index 000000000..90a36d2b3
--- /dev/null
+++ b/android/uhabits-android/src/main/res/layout/widget_checkmarktime.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml b/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml
new file mode 100644
index 000000000..5e988f548
--- /dev/null
+++ b/android/uhabits-android/src/main/res/xml/widget_checkmarktime_info.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
\ No newline at end of file