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..cf1dcfbd2 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,9 +26,9 @@ 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.ui.callbacks.*; +import org.isoron.uhabits.core.ui.screens.habits.list.*; import org.isoron.uhabits.core.ui.screens.habits.show.*; import org.isoron.uhabits.intents.*; @@ -54,6 +54,9 @@ public class ShowHabitScreen extends BaseScreen @NonNull private final IntentFactory intentFactory; + @NonNull + private final NumberPickerFactory numberPickerFactory; + @Inject public ShowHabitScreen(@NonNull BaseActivity activity, @NonNull Habit habit, @@ -61,6 +64,7 @@ public class ShowHabitScreen extends BaseScreen @NonNull ShowHabitsMenu menu, @NonNull ConfirmDeleteDialogFactory confirmDeleteDialogFactory, @NonNull IntentFactory intentFactory, + @NonNull NumberPickerFactory numberPickerFactory, @NonNull Lazy behavior) { super(activity); @@ -71,6 +75,7 @@ public class ShowHabitScreen extends BaseScreen this.habit = habit; this.behavior = behavior; this.confirmDeleteDialogFactory = confirmDeleteDialogFactory; + this.numberPickerFactory = numberPickerFactory; view.setController(this); } @@ -80,6 +85,14 @@ public class ShowHabitScreen extends BaseScreen behavior.get().onEditHistory(); } + @Override + public void showNumberPicker(double value, + @NonNull String unit, + @NonNull ListHabitsBehavior.NumberPickerCallback callback) + { + numberPickerFactory.create(value, unit, callback).show(); + } + @Override public void onToggleCheckmark(Timestamp timestamp, int value) { 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..4589c5057 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 @@ -95,15 +95,17 @@ class AndroidNotificationTray context.getString(R.string.no), pendingIntents.removeRepetition(habit)) + val enterAction = Action( + R.drawable.ic_action_check, + context.getString(R.string.enter), + pendingIntents.setNumericalValue(context, habit, 0, null)) + val wearableBg = decodeResource(context.resources, R.drawable.stripe) // Even though the set of actions is the same on the phone and // on the watch, Pebble requires us to add them to the // WearableExtender. - val wearableExtender = WearableExtender() - .setBackground(wearableBg) - .addAction(addRepetitionAction) - .addAction(removeRepetitionAction) + val wearableExtender = WearableExtender().setBackground(wearableBg) val defaultText = context.getString(R.string.default_reminder_question) val builder = Builder(context, REMINDERS_CHANNEL_ID) @@ -112,13 +114,23 @@ 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) .setWhen(reminderTime) .setShowWhen(true) .setOngoing(preferences.shouldMakeNotificationsSticky()) + if (habit.isNumerical) { + wearableExtender.addAction(enterAction) + builder.addAction(enterAction) + } else { + wearableExtender + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) + builder + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) + } + if (!disableSound) builder.setSound(ringtoneManager.getURI()) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java index 0beeb9ca2..a66cc34a5 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java @@ -18,6 +18,7 @@ import com.android.datetimepicker.time.TimePickerDialog; import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.receivers.*; +import org.isoron.uhabits.utils.*; import java.util.*; @@ -55,6 +56,8 @@ public class SnoozeDelayPickerActivity extends FragmentActivity dialog.getListView().setOnItemClickListener(this); dialog.setOnDismissListener(d -> finish()); dialog.show(); + + SystemUtils.unlockScreen(this); } private void showTimePicker() 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 18474a52b..a0af53a7e 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 @@ -113,6 +113,7 @@ public class WidgetReceiver extends BroadcastReceiver data.getTimestamp()); break; case ACTION_SET_NUMERICAL_VALUE: + context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); Intent numberSelectorIntent = new Intent(context, NumericalCheckmarkWidgetActivity.class); numberSelectorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); numberSelectorIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/SystemUtils.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/SystemUtils.java new file mode 100644 index 000000000..81adbc05e --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/utils/SystemUtils.java @@ -0,0 +1,26 @@ +package org.isoron.uhabits.utils; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; + + +public class SystemUtils +{ + public static boolean isAndroidOOrLater() + { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; + } + + public static void unlockScreen(Activity activity) + { + if (isAndroidOOrLater()) { + KeyguardManager km = + (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE); + km.requestDismissKeyguard(activity, null); + } else { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); + } + } +} 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..042506c0d 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 @@ -30,6 +30,7 @@ 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.utils.* import org.isoron.uhabits.widgets.* class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPickerCallback { @@ -51,6 +52,8 @@ class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPi component.notificationTray) widgetUpdater = component.widgetUpdater showNumberSelector(this) + + SystemUtils.unlockScreen(this) } override fun onNumberPicked(newValue: Double) { diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index f2e0ecd12..1ade96853 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -194,6 +194,7 @@ Every month Cannot be blank Today + Enter No habits found No measurable habits found No yes-or-no habits found diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.java index 1f43ace7b..3f81dfeb2 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.java @@ -23,6 +23,7 @@ import androidx.annotation.*; import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.core.ui.screens.habits.list.*; import javax.inject.*; @@ -58,12 +59,29 @@ public class ShowHabitBehavior public void onToggleCheckmark(Timestamp timestamp, int value) { - commandRunner.execute( - new CreateRepetitionCommand(habitList, habit, timestamp, value), null); + if (habit.isNumerical()) { + CheckmarkList checkmarks = habit.getCheckmarks(); + double oldValue = checkmarks.getValues(timestamp, timestamp)[0]; + + screen.showNumberPicker(oldValue / 1000, habit.getUnit(), newValue -> + { + newValue = Math.round(newValue * 1000); + commandRunner.execute( + new CreateRepetitionCommand(habitList, habit, timestamp, (int) newValue), + habit.getId()); + }); + } else { + commandRunner.execute( + new CreateRepetitionCommand(habitList, habit, timestamp, value), null); + } } public interface Screen { void showEditHistoryScreen(); + + void showNumberPicker(double value, + @NonNull String unit, + @NonNull ListHabitsBehavior.NumberPickerCallback callback); } }