diff --git a/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkButtonView/render_implicit_check.png b/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkButtonView/render_implicit_check.png old mode 100644 new mode 100755 index 2f7529768..e13702baf Binary files a/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkButtonView/render_implicit_check.png and b/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkButtonView/render_implicit_check.png differ diff --git a/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkPanelView/render.png b/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkPanelView/render.png old mode 100644 new mode 100755 index 39b3ebb2c..c55aa1481 Binary files a/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkPanelView/render.png and b/android/uhabits-android/src/androidTest/assets/views-v26/habits/list/CheckmarkPanelView/render.png differ diff --git a/android/uhabits-android/src/main/AndroidManifest.xml b/android/uhabits-android/src/main/AndroidManifest.xml index 13d637217..84b3254b2 100644 --- a/android/uhabits-android/src/main/AndroidManifest.xml +++ b/android/uhabits-android/src/main/AndroidManifest.xml @@ -119,6 +119,17 @@ + + + + + + (buttonId) + button.setOnClickListener{ + callback.onCheckmarkOptionPicked(buttonValue) + dialog.dismiss() + } + button.isPressed = ( + valuesToButton.containsKey(value) && + valuesToButton[value] == buttonId) + button.typeface = InterfaceUtils.getFontAwesome(context) + button.background.setTint(habitColor) + } + + val questionTextView = view.findViewById(R.id.choose_checkmark_question_textview) + var question = context.resources.getString(R.string.default_checkmark_option_question) + if (habit.question.isNotEmpty()) { + question = habit.question.trim('?') + } + val questionFullText = context.resources.getString( + R.string.choose_checkmark_question, question, habitTimestamp) + questionTextView.text = questionFullText + questionTextView.setTextColor(habitColor) + + dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) + + return dialog + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java index 68d761034..cc7356d88 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java @@ -154,7 +154,6 @@ public class HistoryChart extends ScrollableChart newValue = Repetition.nextToggleValue(checkmarks[offset]); checkmarks[offset] = newValue; } - controller.onToggleCheckmark(timestamp, newValue); postInvalidate(); return true; @@ -363,6 +362,18 @@ public class HistoryChart extends ScrollableChart headerOverflow = Math.max(0, headerOverflow - columnWidth); } + private boolean isNotCompleted(int checkmark) + { + return (checkmark == 0 || + (!isNumerical && checkmark == UNCHECKED_EXPLICITLY)); + } + + private boolean isImplicitlyCompleted(int checkmark) + { + if (isNumerical) return checkmark < target; + return (checkmark == SKIPPED || checkmark == CHECKED_IMPLICITLY); + } + private void drawSquare(Canvas canvas, RectF location, GregorianCalendar date, @@ -378,12 +389,12 @@ public class HistoryChart extends ScrollableChart else { checkmark = checkmarks[checkmarkOffset]; - if(checkmark == 0) + if(isNotCompleted(checkmark)) { pSquareBg.setColor(colors[0]); pSquareFg.setColor(textColors[1]); } - else if(checkmark < target) + else if(isImplicitlyCompleted(checkmark)) { pSquareBg.setColor(colors[1]); pSquareFg.setColor(textColors[2]); @@ -452,16 +463,13 @@ public class HistoryChart extends ScrollableChart if (isBackgroundTransparent) primaryColor = ColorUtils.setMinValue(primaryColor, 0.75f); - - int red = Color.red(primaryColor); - int green = Color.green(primaryColor); - int blue = Color.blue(primaryColor); + int lighterPrimaryColor = ColorUtils.setAlpha(primaryColor, 0.5f); if (isBackgroundTransparent) { colors = new int[3]; colors[0] = Color.argb(16, 255, 255, 255); - colors[1] = Color.argb(128, red, green, blue); + colors[1] = lighterPrimaryColor; colors[2] = primaryColor; textColors = new int[3]; @@ -474,7 +482,7 @@ public class HistoryChart extends ScrollableChart { colors = new int[3]; colors[0] = res.getColor(R.attr.lowContrastTextColor); - colors[1] = Color.argb(127, red, green, blue); + colors[1] = lighterPrimaryColor; colors[2] = primaryColor; textColors = new int[3]; diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index e4c3752a1..86867611b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -65,6 +65,7 @@ class ListHabitsScreen private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, private val colorPickerFactory: ColorPickerDialogFactory, private val numberPickerFactory: NumberPickerFactory, + private val checkmarkOptionPickerFactory: CheckmarkOptionPickerFactory, private val behavior: Lazy, private val menu: Lazy, private val selectionMenu: Lazy @@ -204,6 +205,13 @@ class ListHabitsScreen numberPickerFactory.create(value, unit, callback).show() } + override fun showCheckmarkOptions(habit: Habit, + timestamp: Timestamp, + value: Int, + callback: ListHabitsBehavior.CheckmarkOptionsCallback) { + checkmarkOptionPickerFactory.create(habit, timestamp.toString(), value, callback).show() + } + @StringRes private fun getExecuteString(command: Command): Int? { when (command) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index aebdae734..4ee352d9e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -26,6 +26,7 @@ import android.view.* import android.view.View.MeasureSpec.* import com.google.auto.factory.* import org.isoron.androidbase.activities.* +import org.isoron.androidbase.utils.* import org.isoron.uhabits.* import org.isoron.uhabits.core.models.* import org.isoron.uhabits.core.models.Checkmark.* @@ -53,6 +54,7 @@ class CheckmarkButtonView( } var onToggle: (Int) -> Unit = {} + var onToggleWithOptions: () -> Unit = {} private var drawer = Drawer() init { @@ -68,13 +70,22 @@ class CheckmarkButtonView( invalidate() } + fun performToggleWithOptions() { + onToggleWithOptions() + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_PRESS) + } + override fun onClick(v: View) { if (preferences.isShortToggleEnabled) performToggle() + else if (preferences.isAdvancedCheckmarksEnabled) performToggleWithOptions() else showMessage(R.string.long_press_to_toggle) } override fun onLongClick(v: View): Boolean { - performToggle() + if (preferences.isShortToggleEnabled && preferences.isAdvancedCheckmarksEnabled) { + performToggleWithOptions() + } + else performToggle() return true } @@ -102,14 +113,22 @@ class CheckmarkButtonView( } fun draw(canvas: Canvas) { + val lighterColor = ColorUtils.setAlpha(color, 0.5f) + paint.color = when (value) { CHECKED_EXPLICITLY -> color - SKIPPED -> color - else -> lowContrastColor + UNCHECKED_EXPLICITLY -> lowContrastColor + UNCHECKED -> lowContrastColor + else -> lighterColor + } + var unchecked_symbol = R.string.fa_times + if (preferences.isAdvancedCheckmarksEnabled) { + unchecked_symbol = R.string.fa_question } val id = when (value) { SKIPPED -> R.string.fa_skipped - UNCHECKED -> R.string.fa_times + UNCHECKED -> unchecked_symbol + UNCHECKED_EXPLICITLY -> R.string.fa_times else -> R.string.fa_check } val label = resources.getString(id) @@ -121,3 +140,4 @@ class CheckmarkButtonView( } } } + diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index 81ee667c8..ecbd88c4e 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -52,6 +52,12 @@ class CheckmarkPanelView( setupButtons() } + var onToggleWithOptions: (Timestamp) -> Unit = {} + set(value) { + field = value + setupButtons() + } + override fun createButton(): CheckmarkButtonView = buttonFactory.create() @Synchronized @@ -66,6 +72,7 @@ class CheckmarkPanelView( } button.color = color button.onToggle = { value -> onToggle(timestamp, value) } + button.onToggleWithOptions = { onToggleWithOptions (timestamp) } } } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index e7891253d..bd084f1b9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -125,6 +125,10 @@ class HabitCardView( triggerRipple(timestamp) habit?.let { behavior.onToggle(it, timestamp, value) } } + onToggleWithOptions = { timestamp -> + triggerRipple(timestamp) + habit?.let { behavior.onToggleWithOptions(it, timestamp) } + } } numberPanel = numberPanelFactory.create().apply { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.java index 3e85f80b9..8d98617e7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitScreen.java @@ -26,8 +26,8 @@ import androidx.annotation.NonNull; import org.isoron.androidbase.activities.*; import org.isoron.uhabits.*; import org.isoron.uhabits.activities.common.dialogs.*; -import org.isoron.uhabits.activities.habits.edit.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.ui.callbacks.*; import org.isoron.uhabits.core.ui.screens.habits.show.*; import org.isoron.uhabits.intents.*; @@ -49,19 +49,27 @@ public class ShowHabitScreen extends BaseScreen @NonNull private final ConfirmDeleteDialogFactory confirmDeleteDialogFactory; + @NonNull + private final CheckmarkOptionPickerFactory checkmarkOptionPickerFactory; + private final Lazy behavior; @NonNull private final IntentFactory intentFactory; + @NonNull + private final Preferences prefs; + @Inject public ShowHabitScreen(@NonNull BaseActivity activity, @NonNull Habit habit, @NonNull ShowHabitRootView view, @NonNull ShowHabitsMenu menu, @NonNull ConfirmDeleteDialogFactory confirmDeleteDialogFactory, + @NonNull CheckmarkOptionPickerFactory checkmarkOptionPickerFactory, @NonNull IntentFactory intentFactory, - @NonNull Lazy behavior) + @NonNull Lazy behavior, + @NonNull Preferences prefs) { super(activity); this.intentFactory = intentFactory; @@ -71,6 +79,8 @@ public class ShowHabitScreen extends BaseScreen this.habit = habit; this.behavior = behavior; this.confirmDeleteDialogFactory = confirmDeleteDialogFactory; + this.checkmarkOptionPickerFactory = checkmarkOptionPickerFactory; + this.prefs = prefs; view.setController(this); } @@ -83,7 +93,17 @@ public class ShowHabitScreen extends BaseScreen @Override public void onToggleCheckmark(Timestamp timestamp, int value) { - behavior.get().onToggleCheckmark(timestamp, value); + if (prefs.isAdvancedCheckmarksEnabled()) + { + CheckmarkList checkmarks = habit.getCheckmarks(); + int oldValue = checkmarks.getValues(timestamp, timestamp)[0]; + checkmarkOptionPickerFactory.create(habit, timestamp.toString(), oldValue, + newValue -> + { + behavior.get().onToggleCheckmark(timestamp, newValue); + }).show(); + } + else behavior.get().onToggleCheckmark(timestamp, value);; } @Override diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index cb2f84532..047d72f45 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -118,4 +118,14 @@ class PendingIntentFactory if (timestamp != null) putExtra("timestamp", timestamp) }, FLAG_UPDATE_CURRENT) + + fun setYesNoValue(habit: Habit, timestamp: Timestamp?): PendingIntent = + PendingIntent.getBroadcast( + context, 0, + Intent(context, WidgetReceiver::class.java).apply { + data = Uri.parse(habit.uriString) + action = WidgetReceiver.ACTION_SET_YESNO_VALUE + if (timestamp != null) putExtra("timestamp", timestamp.unixTime) + }, + FLAG_UPDATE_CURRENT) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index 1f6ab6ad0..c146dfbf9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -44,7 +44,7 @@ class AndroidNotificationTray private val pendingIntents: PendingIntentFactory, private val preferences: Preferences, private val ringtoneManager: RingtoneManager - ) : NotificationTray.SystemTray { +) : NotificationTray.SystemTray { private var active = HashSet() override fun log(msg: String) { @@ -69,11 +69,11 @@ class AndroidNotificationTray } catch (e: RuntimeException) { // Some Xiaomi phones produce a RuntimeException if custom notification sounds are used. Log.i("AndroidNotificationTray", - "Failed to show notification. Retrying without sound.") + "Failed to show notification. Retrying without sound.") val n = buildNotification(habit, - reminderTime, - timestamp, - disableSound = true) + reminderTime, + timestamp, + disableSound = true) notificationManager.notify(notificationId, n) } @@ -95,6 +95,11 @@ class AndroidNotificationTray context.getString(R.string.no), pendingIntents.removeRepetition(habit)) + val enterRepetitionAction = Action( + R.drawable.ic_action_check, + context.getString(R.string.enter), + pendingIntents.setYesNoValue(habit, timestamp)) + val wearableBg = decodeResource(context.resources, R.drawable.stripe) // Even though the set of actions is the same on the phone and @@ -102,8 +107,13 @@ class AndroidNotificationTray // WearableExtender. val wearableExtender = WearableExtender() .setBackground(wearableBg) - .addAction(addRepetitionAction) - .addAction(removeRepetitionAction) + + if (preferences.isAdvancedCheckmarksEnabled) { + wearableExtender.addAction(enterRepetitionAction) + } else { + wearableExtender.addAction(addRepetitionAction) + .addAction(removeRepetitionAction) + } val defaultText = context.getString(R.string.default_reminder_question) val builder = Builder(context, REMINDERS_CHANNEL_ID) @@ -112,9 +122,14 @@ class AndroidNotificationTray .setContentText(if(habit.question.isBlank()) defaultText else habit.question) .setContentIntent(pendingIntents.showHabit(habit)) .setDeleteIntent(pendingIntents.dismissNotification(habit)) - .addAction(addRepetitionAction) - .addAction(removeRepetitionAction) - .setSound(null) + + if (preferences.isAdvancedCheckmarksEnabled) { + builder.addAction(enterRepetitionAction) + } else { + builder.addAction(addRepetitionAction) + .addAction(removeRepetitionAction) + } + builder.setSound(null) .setWhen(reminderTime) .setShowWhen(true) .setOngoing(preferences.shouldMakeNotificationsSticky()) @@ -126,8 +141,8 @@ class AndroidNotificationTray builder.setLights(Color.RED, 1000, 1000) val snoozeAction = Action(R.drawable.ic_action_snooze, - context.getString(R.string.snooze), - pendingIntents.snoozeNotification(habit)) + context.getString(R.string.snooze), + pendingIntents.snoozeNotification(habit)) wearableExtender.addAction(snoozeAction) builder.addAction(snoozeAction) @@ -142,11 +157,11 @@ class AndroidNotificationTray as NotificationManager if (SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel(REMINDERS_CHANNEL_ID, - context.resources.getString(R.string.reminder), - NotificationManager.IMPORTANCE_DEFAULT) + context.resources.getString(R.string.reminder), + NotificationManager.IMPORTANCE_DEFAULT) notificationManager.createNotificationChannel(channel) } } } -} +} \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java index 2942f8141..8d091bd04 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java @@ -52,6 +52,9 @@ public class WidgetReceiver extends BroadcastReceiver public static final String ACTION_SET_NUMERICAL_VALUE = "org.isoron.uhabits.ACTION_SET_NUMERICAL_VALUE"; + public static final String ACTION_SET_YESNO_VALUE = + "org.isoron.uhabits.ACTION_SET_YESNO_VALUE"; + private static final String TAG = "WidgetReceiver"; @Override @@ -112,6 +115,19 @@ public class WidgetReceiver extends BroadcastReceiver parser.copyIntentData(intent,numberSelectorIntent); context.startActivity(numberSelectorIntent); break; + case ACTION_SET_YESNO_VALUE: + Log.d(TAG, String.format( + "onSetYesNoValue habit=%d timestamp=%d", + data.getHabit().getId(), + data.getTimestamp().getUnixTime())); + context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + Intent checkmarkOptionsSelector = new Intent(context, YesNoCheckmarkWidgetActivity.class); + checkmarkOptionsSelector.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + checkmarkOptionsSelector.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + checkmarkOptionsSelector.setAction(YesNoCheckmarkWidgetActivity.ACTION_SHOW_YESNO_VALUE_ACTIVITY); + parser.copyIntentData(intent, checkmarkOptionsSelector); + context.startActivity(checkmarkOptionsSelector); + break; } } catch (RuntimeException e) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt index 588a7fa25..cd86b1ca4 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt @@ -22,6 +22,7 @@ package org.isoron.uhabits.widgets import android.app.* import android.content.* import android.view.* +import org.isoron.uhabits.* import org.isoron.uhabits.core.models.* import org.isoron.uhabits.utils.* import org.isoron.uhabits.widgets.views.* @@ -36,7 +37,12 @@ open class CheckmarkWidget( return if (habit.isNumerical) { pendingIntentFactory.setNumericalValue(context, habit, 10, null) } else { - pendingIntentFactory.toggleCheckmark(habit, null) + val prefs = (context.applicationContext as HabitsApplication).component.preferences + if (prefs.isAdvancedCheckmarksEnabled) { + pendingIntentFactory.setYesNoValue(habit, null) + } else { + pendingIntentFactory.toggleCheckmark(habit, null) + } } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt index fcba1cce8..7187cb5e9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt @@ -23,7 +23,7 @@ import android.app.* import android.content.* import android.os.* import android.view.* -import android.widget.FrameLayout +import android.widget.* import org.isoron.uhabits.* import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.common.dialogs.* diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/YesNoCheckmarkWidgetActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/YesNoCheckmarkWidgetActivity.kt new file mode 100644 index 000000000..d59c466bd --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/YesNoCheckmarkWidgetActivity.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016-2020 Á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.activities + +import android.app.* +import android.content.* +import android.os.* +import android.view.* +import android.widget.* +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 YesNoCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.CheckmarkOptionsCallback { + + 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 + showCheckmarkOptions(this) + } + + override fun onCheckmarkOptionPicked(newValue: Int) { + behavior.setYesNoValue(data.habit, data.timestamp, newValue) + widgetUpdater.updateWidgets() + finish() + } + + override fun onCheckmarkOptionDismissed() { + finish() + } + + private fun showCheckmarkOptions(context: Context) { + val app = this.applicationContext as HabitsApplication + AndroidThemeSwitcher(this, app.component.preferences).apply() + val oldValue = data.habit.checkmarks.getValues(data.timestamp, data.timestamp)[0] + val checkmarkOptionsPickerFactory = CheckmarkOptionPickerFactory(context) + checkmarkOptionsPickerFactory.create( + data.habit, data.timestamp.toString(), oldValue, this).show() + } + + companion object { + const val ACTION_SHOW_YESNO_VALUE_ACTIVITY = "org.isoron.uhabits.ACTION_SHOW_YESNO_VALUE_ACTIVITY" + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java index c278a6635..04a11136c 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.java @@ -73,27 +73,35 @@ public class CheckmarkWidgetView extends HabitWidgetView { int bgColor; int fgColor; + int lighterActiveColor = ColorUtils.setAlpha(activeColor, 0.5f); 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.UNCHECKED_EXPLICITLY: + bgColor = res.getColor(R.attr.highlightedBackgroundColor); + fgColor = res.getColor(R.attr.highContrastReverseTextColor); + setShadowAlpha(0x4f); + break; + case Checkmark.SKIPPED: case Checkmark.CHECKED_IMPLICITLY: + bgColor = lighterActiveColor; + fgColor = res.getColor(R.attr.highContrastReverseTextColor); + setShadowAlpha(0x4f); + break; 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; } + backgroundPaint.setColor(bgColor); ring.setPercentage(percentage); ring.setColor(fgColor); ring.setBackgroundColor(bgColor); @@ -113,6 +121,13 @@ public class CheckmarkWidgetView extends HabitWidgetView { protected String getText() { + HabitsApplication app = + (HabitsApplication) getContext().getApplicationContext(); + int uncheckedSymbol = R.string.fa_times; + if (app.getComponent().getPreferences().isAdvancedCheckmarksEnabled()) + { + uncheckedSymbol = R.string.fa_question; + } if (isNumerical) return NumberButtonViewKt.toShortString(checkmarkValue / 1000.0); switch (checkmarkState) { case Checkmark.CHECKED_EXPLICITLY: @@ -120,9 +135,11 @@ public class CheckmarkWidgetView extends HabitWidgetView { return getResources().getString(R.string.fa_check); case Checkmark.SKIPPED: return getResources().getString(R.string.fa_skipped); + case Checkmark.UNCHECKED_EXPLICITLY: + return getResources().getString(R.string.fa_times); case Checkmark.UNCHECKED: default: - return getResources().getString(R.string.fa_times); + return getResources().getString(uncheckedSymbol); } } diff --git a/android/uhabits-android/src/main/res/layout/checkmark_option_picker_dialog.xml b/android/uhabits-android/src/main/res/layout/checkmark_option_picker_dialog.xml new file mode 100644 index 000000000..036d74ab3 --- /dev/null +++ b/android/uhabits-android/src/main/res/layout/checkmark_option_picker_dialog.xml @@ -0,0 +1,85 @@ + + + + + + + + + +