From 43e802fb8e7dfe0a94f85584345a8a58df1fe5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Wed, 13 Sep 2017 16:25:24 +0200 Subject: [PATCH 1/9] implement custom snooze for notifications --- uhabits-android/src/main/AndroidManifest.xml | 1 + .../notifications/SnoozeDelayActivity.java | 85 +++++++++++++++++++ .../uhabits/receivers/ReminderController.java | 24 +++++- .../uhabits/receivers/ReminderReceiver.java | 10 ++- .../src/main/res/values/constants.xml | 2 + .../src/main/res/values/strings.xml | 1 + .../receivers/ReminderControllerTest.java | 2 +- 7 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java diff --git a/uhabits-android/src/main/AndroidManifest.xml b/uhabits-android/src/main/AndroidManifest.xml index b7cbb4520..ca802a5d6 100644 --- a/uhabits-android/src/main/AndroidManifest.xml +++ b/uhabits-android/src/main/AndroidManifest.xml @@ -91,6 +91,7 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activities.habits.list.ListHabitsActivity"/> + time) + time += DateUtils.DAY_LENGTH; + time = applyTimezone(time); + + Intent intent = new Intent( ReminderReceiver.ACTION_SNOOZE_REMINDER_SET, getIntent().getData(), + this, ReminderReceiver.class ); + intent.putExtra("reminderTime", time); + sendBroadcast(intent); + + finish(); + } + + @Override + public void onTimeCleared(RadialPickerLayout view) + { + Intent intent = new Intent( ReminderReceiver.ACTION_DISMISS_REMINDER, getIntent().getData(), + this, ReminderReceiver.class ); + sendBroadcast(intent); + + finish(); + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java index ae88f55c9..179b16e39 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java @@ -19,12 +19,15 @@ package org.isoron.uhabits.receivers; +import android.content.*; +import android.net.*; import android.support.annotation.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.reminders.*; import org.isoron.uhabits.core.ui.*; +import org.isoron.uhabits.notifications.*; import javax.inject.*; @@ -65,13 +68,32 @@ public class ReminderController reminderScheduler.scheduleAll(); } - public void onSnooze(@NonNull Habit habit) + public void onSnooze(@NonNull Habit habit, final Context context) { long snoozeInterval = preferences.getSnoozeInterval(); + if (snoozeInterval < 0) + { + context.sendBroadcast( new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + Intent intent = new Intent( SnoozeDelayActivity.ACTION_ASK_SNOOZE, Uri.parse( habit.getUriString()), + context, SnoozeDelayActivity.class ); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + return; + } + + snoozeNotificationAddDelay(habit, snoozeInterval); + } + + public void snoozeNotificationAddDelay(@NonNull Habit habit, long snoozeInterval) + { long now = applyTimezone(getLocalTime()); long reminderTime = now + snoozeInterval * 60 * 1000; + snoozeNotificationSetReminderTime(habit, reminderTime); + } + public void snoozeNotificationSetReminderTime(@NonNull Habit habit, long reminderTime) + { reminderScheduler.schedule(habit, reminderTime); notificationTray.cancel(habit); } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index cb382a950..c6990b4dd 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -46,6 +46,9 @@ public class ReminderReceiver extends BroadcastReceiver public static final String ACTION_SNOOZE_REMINDER = "org.isoron.uhabits.ACTION_SNOOZE_REMINDER"; + public static final String ACTION_SNOOZE_REMINDER_SET = + "org.isoron.uhabits.ACTION_SNOOZE_REMINDER_SET"; + private static final String TAG = "ReminderReceiver"; @Override @@ -90,7 +93,12 @@ public class ReminderReceiver extends BroadcastReceiver case ACTION_SNOOZE_REMINDER: if (habit == null) return; - reminderController.onSnooze(habit); + reminderController.onSnooze(habit,context); + break; + + case ACTION_SNOOZE_REMINDER_SET: + if (habit == null) return; + reminderController.snoozeNotificationSetReminderTime(habit, reminderTime); break; case Intent.ACTION_BOOT_COMPLETED: diff --git a/uhabits-android/src/main/res/values/constants.xml b/uhabits-android/src/main/res/values/constants.xml index 94ae54340..1b46ccc5d 100644 --- a/uhabits-android/src/main/res/values/constants.xml +++ b/uhabits-android/src/main/res/values/constants.xml @@ -35,6 +35,7 @@ @string/interval_4_hour @string/interval_8_hour @string/interval_24_hour + @string/interval_always_ask @@ -45,6 +46,7 @@ 240 480 1440 + -1 diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index 1671734fd..821cf2298 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -83,6 +83,7 @@ 4 hours 8 hours 24 hours + Always ask Toggle with short press Put checkmarks with a single tap instead of press-and-hold. More convenient, but might cause accidental toggles. Snooze interval on reminders diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java index 93b199a10..7b0406832 100644 --- a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java +++ b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java @@ -70,7 +70,7 @@ public class ReminderControllerTest extends BaseAndroidJVMTest DateUtils.setFixedLocalTime(now); when(preferences.getSnoozeInterval()).thenReturn(15L); - controller.onSnooze(habit); + controller.onSnooze(habit,null); verify(reminderScheduler).schedule(habit, nowTz + 900000); verify(notificationTray).cancel(habit); From 0421ca054965816cfb31f06e7095074ee2008a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Thu, 14 Sep 2017 10:32:59 +0200 Subject: [PATCH 2/9] make snooze time dialog follow night mode setting --- .../org/isoron/uhabits/notifications/SnoozeDelayActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java index 2de2c2ae7..7a3d27b5f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java @@ -8,11 +8,13 @@ import android.util.*; import com.android.datetimepicker.time.*; +import org.isoron.uhabits.*; import org.isoron.uhabits.core.utils.DateUtils; import org.isoron.uhabits.receivers.*; import java.util.*; +import static org.isoron.uhabits.core.ui.ThemeSwitcher.THEME_DARK; import static org.isoron.uhabits.core.utils.DateUtils.applyTimezone; public class SnoozeDelayActivity extends FragmentActivity implements @@ -50,6 +52,8 @@ public class SnoozeDelayActivity extends FragmentActivity implements TimePickerDialog dialog; dialog = TimePickerDialog.newInstance(this, hour, minute, DateFormat.is24HourFormat(this)); + HabitsApplicationComponent component = ((HabitsApplication) getApplicationContext()).getComponent(); + dialog.setThemeDark(component.getPreferences().getTheme() == THEME_DARK); dialog.show(getSupportFragmentManager(),"timePicker"); } From aac59367dcc4b19d09972dbb4523db98d4a206f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Thu, 14 Sep 2017 13:02:05 +0200 Subject: [PATCH 3/9] properly handle the activity window of the snooze time dialog --- .../datetimepicker/time/TimePickerDialog.java | 12 ++++++++++++ uhabits-android/src/main/AndroidManifest.xml | 6 +++++- .../uhabits/notifications/SnoozeDelayActivity.java | 9 ++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java b/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java index 0bbb741e2..7cbdd3cd3 100644 --- a/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java +++ b/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java @@ -63,6 +63,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue private static final int PULSE_ANIMATOR_DELAY = 300; private OnTimeSetListener mCallback; + private DialogInterface.OnDismissListener dismissListener; private HapticFeedbackController mHapticFeedbackController; @@ -998,4 +999,15 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue return false; } } + + public void setDismissListener( DialogInterface.OnDismissListener listener ) { + dismissListener = listener; + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + if( dismissListener != null ) + dismissListener.onDismiss(dialog); + } } diff --git a/uhabits-android/src/main/AndroidManifest.xml b/uhabits-android/src/main/AndroidManifest.xml index ca802a5d6..99e5b20fb 100644 --- a/uhabits-android/src/main/AndroidManifest.xml +++ b/uhabits-android/src/main/AndroidManifest.xml @@ -91,7 +91,11 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activities.habits.list.ListHabitsActivity"/> - + + Date: Fri, 15 Sep 2017 11:29:36 +0200 Subject: [PATCH 4/9] when asking for snooze delay, first show a list of common options --- .../notifications/SnoozeDelayActivity.java | 34 ++++++++++++++++++- .../uhabits/receivers/ReminderReceiver.java | 9 +++++ .../src/main/res/values/constants.xml | 22 ++++++++++++ .../src/main/res/values/strings.xml | 2 ++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java index a32871f65..be0ef36d1 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java @@ -1,5 +1,6 @@ package org.isoron.uhabits.notifications; +import android.app.*; import android.content.*; import android.os.*; import android.support.v4.app.*; @@ -7,6 +8,7 @@ import android.text.format.*; import android.util.*; import com.android.datetimepicker.time.*; +import com.android.datetimepicker.time.TimePickerDialog; import org.isoron.uhabits.*; import org.isoron.uhabits.core.utils.DateUtils; @@ -18,12 +20,14 @@ import static org.isoron.uhabits.core.ui.ThemeSwitcher.THEME_DARK; import static org.isoron.uhabits.core.utils.DateUtils.applyTimezone; public class SnoozeDelayActivity extends FragmentActivity implements - TimePickerDialog.OnTimeSetListener, DialogInterface.OnDismissListener { + TimePickerDialog.OnTimeSetListener, DialogInterface.OnDismissListener, DialogInterface.OnClickListener { public static final String ACTION_ASK_SNOOZE = "org.isoron.uhabits.ACTION_ASK_SNOOZE"; private static final String TAG = "SnoozeDelayActivity"; + private AlertDialog activeDelayDialog; + @Override protected void onCreate(Bundle bundle) { @@ -45,6 +49,34 @@ public class SnoozeDelayActivity extends FragmentActivity implements } private void AskSnooze() + { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.select_snooze_delay) + .setItems(R.array.snooze_interval_names_reminder, this); + AlertDialog dialog = builder.create(); + dialog.setOnDismissListener(this); + activeDelayDialog = dialog; + dialog.show(); + } + + @Override + public void onClick(DialogInterface dialogInterface, int i) + { + int[] snoozeDelay = getResources().getIntArray(R.array.snooze_interval_values_reminder); + assert (i >= 0 && i <= snoozeDelay.length); + if( snoozeDelay[ i ] < 0 ) + { + activeDelayDialog.setOnDismissListener(null); + AskCustomSnooze(); + return; + } + Intent intent = new Intent( ReminderReceiver.ACTION_SNOOZE_REMINDER_DELAY, getIntent().getData(), + this, ReminderReceiver.class ); + intent.putExtra("snoozeDelay", snoozeDelay[ i ]); + sendBroadcast(intent); + } + + private void AskCustomSnooze() { final Calendar calendar = Calendar.getInstance(); int hour = calendar.get(Calendar.HOUR_OF_DAY); diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index c6990b4dd..b80baf11b 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -49,6 +49,9 @@ public class ReminderReceiver extends BroadcastReceiver public static final String ACTION_SNOOZE_REMINDER_SET = "org.isoron.uhabits.ACTION_SNOOZE_REMINDER_SET"; + public static final String ACTION_SNOOZE_REMINDER_DELAY = + "org.isoron.uhabits.ACTION_SNOOZE_REMINDER_DELAY"; + private static final String TAG = "ReminderReceiver"; @Override @@ -101,6 +104,12 @@ public class ReminderReceiver extends BroadcastReceiver reminderController.snoozeNotificationSetReminderTime(habit, reminderTime); break; + case ACTION_SNOOZE_REMINDER_DELAY: + if (habit == null) return; + long snoozeDelay = intent.getIntExtra("snoozeDelay", 0); + reminderController.snoozeNotificationAddDelay(habit, snoozeDelay); + break; + case Intent.ACTION_BOOT_COMPLETED: reminderController.onBootCompleted(); break; diff --git a/uhabits-android/src/main/res/values/constants.xml b/uhabits-android/src/main/res/values/constants.xml index 1b46ccc5d..e8d08c0b5 100644 --- a/uhabits-android/src/main/res/values/constants.xml +++ b/uhabits-android/src/main/res/values/constants.xml @@ -49,6 +49,28 @@ -1 + + @string/interval_15_minutes + @string/interval_30_minutes + @string/interval_1_hour + @string/interval_2_hour + @string/interval_4_hour + @string/interval_8_hour + @string/interval_24_hour + @string/interval_custom + + + + 15 + 30 + 60 + 120 + 240 + 480 + 1440 + -1 + + @string/every_day @string/every_week diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index 821cf2298..814a53d32 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -84,6 +84,7 @@ 8 hours 24 hours Always ask + Custom... Toggle with short press Put checkmarks with a single tap instead of press-and-hold. More convenient, but might cause accidental toggles. Snooze interval on reminders @@ -96,6 +97,7 @@ Name Settings Snooze interval + Select snooze delay Did you know? To rearrange the entries, press-and-hold on the name of the habit, then drag it to the correct place. From e970473876838129dd0ae524da11c0352eac255a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Fri, 15 Sep 2017 11:58:58 +0200 Subject: [PATCH 5/9] make notification snooze popup follow night mode setting --- .../isoron/uhabits/notifications/SnoozeDelayActivity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java index be0ef36d1..769ba7713 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java @@ -4,6 +4,7 @@ import android.app.*; import android.content.*; import android.os.*; import android.support.v4.app.*; +import android.support.v7.view.*; import android.text.format.*; import android.util.*; @@ -50,7 +51,10 @@ public class SnoozeDelayActivity extends FragmentActivity implements private void AskSnooze() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); + HabitsApplicationComponent component = ((HabitsApplication) getApplicationContext()).getComponent(); + int theme = component.getPreferences().getTheme() == THEME_DARK + ? R.style.Theme_AppCompat_Dialog_Alert : R.style.Theme_AppCompat_Light_Dialog_Alert; + AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, theme)); builder.setTitle(R.string.select_snooze_delay) .setItems(R.array.snooze_interval_names_reminder, this); AlertDialog dialog = builder.create(); From a201273781f214da51e42ebee3370ee14b911ee2 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Mon, 9 Oct 2017 19:58:48 -0500 Subject: [PATCH 6/9] Refactoring --- android-pickers/build.gradle | 5 + .../datetimepicker/time/TimePickerDialog.java | 2 +- uhabits-android/src/main/AndroidManifest.xml | 2 +- .../uhabits/HabitsApplicationComponent.java | 3 + .../notifications/SnoozeDelayActivity.java | 128 ------------------ .../SnoozeDelayPickerActivity.java | 85 ++++++++++++ .../uhabits/receivers/ReminderController.java | 56 ++++---- .../uhabits/receivers/ReminderReceiver.java | 55 ++------ .../src/main/res/values/constants.xml | 4 +- .../receivers/ReminderControllerTest.java | 4 +- .../isoron/uhabits/core/models/Reminder.java | 32 +++-- .../core/reminders/ReminderScheduler.java | 32 ++--- .../isoron/uhabits/core/utils/DateUtils.java | 14 ++ 13 files changed, 189 insertions(+), 233 deletions(-) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java diff --git a/android-pickers/build.gradle b/android-pickers/build.gradle index fc75627d8..e88f868cc 100644 --- a/android-pickers/build.gradle +++ b/android-pickers/build.gradle @@ -18,6 +18,11 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } } dependencies { diff --git a/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java b/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java index 7cbdd3cd3..06c121b3c 100644 --- a/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java +++ b/android-pickers/src/main/java/com/android/datetimepicker/time/TimePickerDialog.java @@ -117,7 +117,7 @@ public class TimePickerDialog extends AppCompatDialogFragment implements OnValue */ void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute); - void onTimeCleared(RadialPickerLayout view); + default void onTimeCleared(RadialPickerLayout view) {} } public TimePickerDialog() { diff --git a/uhabits-android/src/main/AndroidManifest.xml b/uhabits-android/src/main/AndroidManifest.xml index 99e5b20fb..be3dff213 100644 --- a/uhabits-android/src/main/AndroidManifest.xml +++ b/uhabits-android/src/main/AndroidManifest.xml @@ -91,7 +91,7 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activities.habits.list.ListHabitsActivity"/> - diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java index 375d2db34..3fd635f22 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java @@ -33,6 +33,7 @@ import org.isoron.uhabits.core.ui.*; import org.isoron.uhabits.core.ui.screens.habits.list.*; import org.isoron.uhabits.core.utils.*; import org.isoron.uhabits.intents.*; +import org.isoron.uhabits.receivers.*; import org.isoron.uhabits.sync.*; import org.isoron.uhabits.tasks.*; import org.isoron.uhabits.widgets.*; @@ -80,6 +81,8 @@ public interface HabitsApplicationComponent ReminderScheduler getReminderScheduler(); + ReminderController getReminderController(); + SyncManager getSyncManager(); TaskRunner getTaskRunner(); diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java deleted file mode 100644 index 769ba7713..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayActivity.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.isoron.uhabits.notifications; - -import android.app.*; -import android.content.*; -import android.os.*; -import android.support.v4.app.*; -import android.support.v7.view.*; -import android.text.format.*; -import android.util.*; - -import com.android.datetimepicker.time.*; -import com.android.datetimepicker.time.TimePickerDialog; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.utils.DateUtils; -import org.isoron.uhabits.receivers.*; - -import java.util.*; - -import static org.isoron.uhabits.core.ui.ThemeSwitcher.THEME_DARK; -import static org.isoron.uhabits.core.utils.DateUtils.applyTimezone; - -public class SnoozeDelayActivity extends FragmentActivity implements - TimePickerDialog.OnTimeSetListener, DialogInterface.OnDismissListener, DialogInterface.OnClickListener { - - public static final String ACTION_ASK_SNOOZE = "org.isoron.uhabits.ACTION_ASK_SNOOZE"; - - private static final String TAG = "SnoozeDelayActivity"; - - private AlertDialog activeDelayDialog; - - @Override - protected void onCreate(Bundle bundle) - { - super.onCreate(bundle); - Intent intent = getIntent(); - try - { - switch (intent.getAction()) - { - case ACTION_ASK_SNOOZE: - AskSnooze(); - break; - } - } - catch (RuntimeException e) - { - Log.e(TAG, "could not process intent", e); - } - } - - private void AskSnooze() - { - HabitsApplicationComponent component = ((HabitsApplication) getApplicationContext()).getComponent(); - int theme = component.getPreferences().getTheme() == THEME_DARK - ? R.style.Theme_AppCompat_Dialog_Alert : R.style.Theme_AppCompat_Light_Dialog_Alert; - AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, theme)); - builder.setTitle(R.string.select_snooze_delay) - .setItems(R.array.snooze_interval_names_reminder, this); - AlertDialog dialog = builder.create(); - dialog.setOnDismissListener(this); - activeDelayDialog = dialog; - dialog.show(); - } - - @Override - public void onClick(DialogInterface dialogInterface, int i) - { - int[] snoozeDelay = getResources().getIntArray(R.array.snooze_interval_values_reminder); - assert (i >= 0 && i <= snoozeDelay.length); - if( snoozeDelay[ i ] < 0 ) - { - activeDelayDialog.setOnDismissListener(null); - AskCustomSnooze(); - return; - } - Intent intent = new Intent( ReminderReceiver.ACTION_SNOOZE_REMINDER_DELAY, getIntent().getData(), - this, ReminderReceiver.class ); - intent.putExtra("snoozeDelay", snoozeDelay[ i ]); - sendBroadcast(intent); - } - - private void AskCustomSnooze() - { - final Calendar calendar = Calendar.getInstance(); - int hour = calendar.get(Calendar.HOUR_OF_DAY); - int minute = calendar.get(Calendar.MINUTE); - TimePickerDialog dialog; - dialog = TimePickerDialog.newInstance(this, - hour, minute, DateFormat.is24HourFormat(this)); - HabitsApplicationComponent component = ((HabitsApplication) getApplicationContext()).getComponent(); - dialog.setThemeDark(component.getPreferences().getTheme() == THEME_DARK); - dialog.setDismissListener(this); - dialog.show(getSupportFragmentManager(),"timePicker"); - } - - @Override - public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) - { - Calendar calendar = DateUtils.getStartOfTodayCalendar(); - calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); - calendar.set(Calendar.MINUTE, minute); - calendar.set(Calendar.SECOND, 0); - Long time = calendar.getTimeInMillis(); - if (DateUtils.getLocalTime() > time) - time += DateUtils.DAY_LENGTH; - time = applyTimezone(time); - - Intent intent = new Intent( ReminderReceiver.ACTION_SNOOZE_REMINDER_SET, getIntent().getData(), - this, ReminderReceiver.class ); - intent.putExtra("reminderTime", time); - sendBroadcast(intent); - } - - @Override - public void onTimeCleared(RadialPickerLayout view) - { - Intent intent = new Intent( ReminderReceiver.ACTION_DISMISS_REMINDER, getIntent().getData(), - this, ReminderReceiver.class ); - sendBroadcast(intent); - } - - @Override - public void onDismiss(DialogInterface dialogInterface) - { - finish(); - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java new file mode 100644 index 000000000..ab51a7983 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java @@ -0,0 +1,85 @@ +package org.isoron.uhabits.notifications; + +import android.os.*; +import android.support.annotation.*; +import android.support.v4.app.*; +import android.support.v7.app.*; +import android.text.format.*; +import android.view.*; +import android.widget.*; + +import com.android.datetimepicker.time.*; + +import org.isoron.uhabits.*; +import org.isoron.uhabits.R; +import org.isoron.uhabits.core.models.*; +import org.isoron.uhabits.receivers.*; + +import java.util.*; + +import butterknife.*; + +import static android.content.ContentUris.*; + +public class SnoozeDelayPickerActivity extends AppCompatActivity implements AdapterView + .OnItemClickListener +{ + public static final String ACTION_ASK_SNOOZE = "org.isoron.uhabits.ACTION_ASK_SNOOZE"; + + private Habit habit; + + private ReminderController reminderController; + + @BindArray(R.array.snooze_picker_names) + protected String[] snoozeNames; + + @BindArray(R.array.snooze_picker_values) + protected int[] snoozeValues; + + @Override + protected void onCreate(@Nullable Bundle bundle) + { + super.onCreate(bundle); + if (getIntent() == null) finish(); + if (getIntent().getData() == null) finish(); + + HabitsApplication app = (HabitsApplication) getApplicationContext(); + HabitsApplicationComponent appComponent = app.getComponent(); + reminderController = appComponent.getReminderController(); + habit = appComponent.getHabitList().getById(parseId(getIntent().getData())); + if (habit == null) finish(); + + setTheme(R.style.Theme_AppCompat_Light_Dialog_Alert); + ButterKnife.bind(this); + + ListView listView = new ListView(this); + listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + snoozeNames)); + listView.setOnItemClickListener(this); + setContentView(listView); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) + { + if (snoozeValues[position] >= 0) + { + reminderController.onSnoozeDelayPicked(habit, snoozeValues[position]); + finish(); + } + else showTimePicker(); + } + + private void showTimePicker() + { + final Calendar calendar = Calendar.getInstance(); + int defaultHour = calendar.get(Calendar.HOUR_OF_DAY); + int defaultMinute = calendar.get(Calendar.MINUTE); + TimePickerDialog dialog = TimePickerDialog.newInstance( + (view, hour, minute) -> + reminderController.onSnoozeTimePicked(habit, hour, minute), + defaultHour, defaultMinute, DateFormat.is24HourFormat(this)); + + dialog.show(getSupportFragmentManager(), "timePicker"); + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java index 179b16e39..0d07a1212 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java @@ -23,18 +23,17 @@ import android.content.*; import android.net.*; import android.support.annotation.*; +import org.isoron.uhabits.core.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.reminders.*; import org.isoron.uhabits.core.ui.*; +import org.isoron.uhabits.core.utils.*; import org.isoron.uhabits.notifications.*; import javax.inject.*; -import static org.isoron.uhabits.core.utils.DateUtils.applyTimezone; -import static org.isoron.uhabits.core.utils.DateUtils.getLocalTime; - -@ReceiverScope +@AppScope public class ReminderController { @NonNull @@ -43,6 +42,7 @@ public class ReminderController @NonNull private final NotificationTray notificationTray; + @NonNull private Preferences preferences; @Inject @@ -68,33 +68,25 @@ public class ReminderController reminderScheduler.scheduleAll(); } - public void onSnooze(@NonNull Habit habit, final Context context) + public void onSnoozePressed(@NonNull Habit habit, final Context context) { - long snoozeInterval = preferences.getSnoozeInterval(); - - if (snoozeInterval < 0) - { - context.sendBroadcast( new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - Intent intent = new Intent( SnoozeDelayActivity.ACTION_ASK_SNOOZE, Uri.parse( habit.getUriString()), - context, SnoozeDelayActivity.class ); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - return; - } - - snoozeNotificationAddDelay(habit, snoozeInterval); + long delay = preferences.getSnoozeInterval(); + + if (delay < 0) + showSnoozeDelayPicker(habit, context); + else + scheduleReminderMinutesFromNow(habit, delay); } - public void snoozeNotificationAddDelay(@NonNull Habit habit, long snoozeInterval) + public void onSnoozeDelayPicked(Habit habit, int delay) { - long now = applyTimezone(getLocalTime()); - long reminderTime = now + snoozeInterval * 60 * 1000; - snoozeNotificationSetReminderTime(habit, reminderTime); + scheduleReminderMinutesFromNow(habit, delay); } - public void snoozeNotificationSetReminderTime(@NonNull Habit habit, long reminderTime) + public void onSnoozeTimePicked(Habit habit, int hour, int minute) { - reminderScheduler.schedule(habit, reminderTime); + Long time = DateUtils.getUpcomingTimeInMillis(hour, minute); + reminderScheduler.scheduleAtTime(habit, time); notificationTray.cancel(habit); } @@ -102,4 +94,20 @@ public class ReminderController { notificationTray.cancel(habit); } + + private void scheduleReminderMinutesFromNow(Habit habit, long minutes) + { + reminderScheduler.scheduleMinutesFromNow(habit, minutes); + notificationTray.cancel(habit); + } + + private void showSnoozeDelayPicker(@NonNull Habit habit, Context context) + { + context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + Intent intent = new Intent(SnoozeDelayPickerActivity.ACTION_ASK_SNOOZE, + Uri.parse(habit.getUriString()), + context, SnoozeDelayPickerActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index b80baf11b..dff612345 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -20,14 +20,13 @@ package org.isoron.uhabits.receivers; import android.content.*; +import android.support.annotation.*; import android.util.*; import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.utils.*; -import dagger.*; - import static android.content.ContentUris.*; /** @@ -38,36 +37,26 @@ import static android.content.ContentUris.*; public class ReminderReceiver extends BroadcastReceiver { public static final String ACTION_DISMISS_REMINDER = - "org.isoron.uhabits.ACTION_DISMISS_REMINDER"; + "org.isoron.uhabits.ACTION_DISMISS_REMINDER"; public static final String ACTION_SHOW_REMINDER = - "org.isoron.uhabits.ACTION_SHOW_REMINDER"; + "org.isoron.uhabits.ACTION_SHOW_REMINDER"; public static final String ACTION_SNOOZE_REMINDER = - "org.isoron.uhabits.ACTION_SNOOZE_REMINDER"; - - public static final String ACTION_SNOOZE_REMINDER_SET = - "org.isoron.uhabits.ACTION_SNOOZE_REMINDER_SET"; - - public static final String ACTION_SNOOZE_REMINDER_DELAY = - "org.isoron.uhabits.ACTION_SNOOZE_REMINDER_DELAY"; + "org.isoron.uhabits.ACTION_SNOOZE_REMINDER"; private static final String TAG = "ReminderReceiver"; @Override - public void onReceive(final Context context, Intent intent) + public void onReceive(@Nullable final Context context, @Nullable Intent intent) { - HabitsApplication app = - (HabitsApplication) context.getApplicationContext(); - - ReminderComponent component = DaggerReminderReceiver_ReminderComponent - .builder() - .habitsApplicationComponent(app.getComponent()) - .build(); + if (context == null || intent == null) return; + if (intent.getAction() == null) return; - HabitList habits = app.getComponent().getHabitList(); - ReminderController reminderController = - component.getReminderController(); + HabitsApplication app = (HabitsApplication) context.getApplicationContext(); + HabitsApplicationComponent appComponent = app.getComponent(); + HabitList habits = appComponent.getHabitList(); + ReminderController reminderController = appComponent.getReminderController(); Log.i(TAG, String.format("Received intent: %s", intent.toString())); @@ -86,7 +75,7 @@ public class ReminderReceiver extends BroadcastReceiver case ACTION_SHOW_REMINDER: if (habit == null) return; reminderController.onShowReminder(habit, - new Timestamp(timestamp), reminderTime); + new Timestamp(timestamp), reminderTime); break; case ACTION_DISMISS_REMINDER: @@ -96,18 +85,7 @@ public class ReminderReceiver extends BroadcastReceiver case ACTION_SNOOZE_REMINDER: if (habit == null) return; - reminderController.onSnooze(habit,context); - break; - - case ACTION_SNOOZE_REMINDER_SET: - if (habit == null) return; - reminderController.snoozeNotificationSetReminderTime(habit, reminderTime); - break; - - case ACTION_SNOOZE_REMINDER_DELAY: - if (habit == null) return; - long snoozeDelay = intent.getIntExtra("snoozeDelay", 0); - reminderController.snoozeNotificationAddDelay(habit, snoozeDelay); + reminderController.onSnoozePressed(habit, context); break; case Intent.ACTION_BOOT_COMPLETED: @@ -120,11 +98,4 @@ public class ReminderReceiver extends BroadcastReceiver Log.e(TAG, "could not process intent", e); } } - - @ReceiverScope - @Component(dependencies = HabitsApplicationComponent.class) - interface ReminderComponent - { - ReminderController getReminderController(); - } } diff --git a/uhabits-android/src/main/res/values/constants.xml b/uhabits-android/src/main/res/values/constants.xml index e8d08c0b5..34e8136a5 100644 --- a/uhabits-android/src/main/res/values/constants.xml +++ b/uhabits-android/src/main/res/values/constants.xml @@ -49,7 +49,7 @@ -1 - + @string/interval_15_minutes @string/interval_30_minutes @string/interval_1_hour @@ -60,7 +60,7 @@ @string/interval_custom - + 15 30 60 diff --git a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java index 7b0406832..69528118a 100644 --- a/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java +++ b/uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java @@ -70,9 +70,9 @@ public class ReminderControllerTest extends BaseAndroidJVMTest DateUtils.setFixedLocalTime(now); when(preferences.getSnoozeInterval()).thenReturn(15L); - controller.onSnooze(habit,null); + controller.onSnoozePressed(habit,null); - verify(reminderScheduler).schedule(habit, nowTz + 900000); + verify(reminderScheduler).scheduleAtTime(habit, nowTz + 900000); verify(notificationTray).cancel(habit); } diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Reminder.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Reminder.java index 870954605..8cb0d31f0 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Reminder.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Reminder.java @@ -22,8 +22,9 @@ package org.isoron.uhabits.core.models; import android.support.annotation.*; import org.apache.commons.lang3.builder.*; +import org.isoron.uhabits.core.utils.*; -import static org.isoron.uhabits.core.utils.StringUtils.defaultToStringStyle; +import static org.isoron.uhabits.core.utils.StringUtils.*; public final class Reminder { @@ -56,6 +57,11 @@ public final class Reminder return minute; } + public long getTimeInMillis() + { + return DateUtils.getUpcomingTimeInMillis(hour, minute); + } + @Override public boolean equals(Object o) { @@ -66,29 +72,29 @@ public final class Reminder Reminder reminder = (Reminder) o; return new EqualsBuilder() - .append(hour, reminder.hour) - .append(minute, reminder.minute) - .append(days, reminder.days) - .isEquals(); + .append(hour, reminder.hour) + .append(minute, reminder.minute) + .append(days, reminder.days) + .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 37) - .append(hour) - .append(minute) - .append(days) - .toHashCode(); + .append(hour) + .append(minute) + .append(days) + .toHashCode(); } @Override public String toString() { return new ToStringBuilder(this, defaultToStringStyle()) - .append("hour", hour) - .append("minute", minute) - .append("days", days) - .toString(); + .append("hour", hour) + .append("minute", minute) + .append("days", days) + .toString(); } } diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java index e31ed71ed..ce4059ae8 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java @@ -24,9 +24,6 @@ import android.support.annotation.*; import org.isoron.uhabits.core.*; import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.utils.*; - -import java.util.*; import javax.inject.*; @@ -60,14 +57,17 @@ public class ReminderScheduler implements CommandRunner.Listener scheduleAll(); } - public void schedule(@NonNull Habit habit, @Nullable Long reminderTime) + public void schedule(@NonNull Habit habit) + { + Long reminderTime = habit.getReminder().getTimeInMillis(); + scheduleAtTime(habit, reminderTime); + } + + public void scheduleAtTime(@NonNull Habit habit, @NonNull Long reminderTime) { if (!habit.hasReminder()) return; if (habit.isArchived()) return; - Reminder reminder = habit.getReminder(); - if (reminderTime == null) reminderTime = getReminderTime(reminder); long timestamp = getStartOfDay(removeTimezone(reminderTime)); - sys.scheduleShowReminder(reminderTime, habit, timestamp); } @@ -76,7 +76,7 @@ public class ReminderScheduler implements CommandRunner.Listener HabitList reminderHabits = habitList.getFiltered(HabitMatcher.WITH_ALARM); for (Habit habit : reminderHabits) - schedule(habit, null); + schedule(habit); } public void startListening() @@ -89,19 +89,11 @@ public class ReminderScheduler implements CommandRunner.Listener commandRunner.removeListener(this); } - @NonNull - private Long getReminderTime(@NonNull Reminder reminder) + public void scheduleMinutesFromNow(Habit habit, long minutes) { - Calendar calendar = DateUtils.getStartOfTodayCalendar(); - calendar.set(Calendar.HOUR_OF_DAY, reminder.getHour()); - calendar.set(Calendar.MINUTE, reminder.getMinute()); - calendar.set(Calendar.SECOND, 0); - Long time = calendar.getTimeInMillis(); - - if (DateUtils.getLocalTime() > time) - time += DateUtils.DAY_LENGTH; - - return applyTimezone(time); + long now = applyTimezone(getLocalTime()); + long reminderTime = now + minutes * 60 * 1000; + scheduleAtTime(habit, reminderTime); } public interface SystemScheduler diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java index ff52f47db..149af5969 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java @@ -240,6 +240,20 @@ public abstract class DateUtils } } + public static long getUpcomingTimeInMillis(int hour, int minute) + { + Calendar calendar = DateUtils.getStartOfTodayCalendar(); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + calendar.set(Calendar.SECOND, 0); + Long time = calendar.getTimeInMillis(); + + if (DateUtils.getLocalTime() > time) + time += DateUtils.DAY_LENGTH; + + return applyTimezone(time); + } + public enum TruncateField { MONTH, WEEK_NUMBER, YEAR, QUARTER From 2a4a7c975f3e71be3519156653ae66be541122fb Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 14 Nov 2017 22:35:37 -0600 Subject: [PATCH 7/9] Add action to show reminder right now (for developers) --- .../habits/list/ListHabitsSelectionMenu.kt | 15 ++++++++++++++- .../src/main/res/menu/list_habits_selection.xml | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt index 9493b651d..65c75cc01 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt @@ -25,7 +25,10 @@ import org.isoron.androidbase.activities.* import org.isoron.uhabits.* import org.isoron.uhabits.activities.habits.list.views.* import org.isoron.uhabits.core.commands.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.ui.* import org.isoron.uhabits.core.ui.screens.habits.list.* +import org.isoron.uhabits.core.utils.* import javax.inject.* @ActivityScope @@ -33,8 +36,10 @@ class ListHabitsSelectionMenu @Inject constructor( private val screen: ListHabitsScreen, private val listAdapter: HabitCardListAdapter, var commandRunner: CommandRunner, + private val prefs: Preferences, private val behavior: ListHabitsSelectionMenuBehavior, - private val listController: Lazy + private val listController: Lazy, + private val notificationTray: NotificationTray ) : BaseSelectionMenu() { override fun onFinish() { @@ -69,6 +74,12 @@ class ListHabitsSelectionMenu @Inject constructor( return true } + R.id.action_notify -> { + for(h in listAdapter.selected) + notificationTray.show(h, DateUtils.getToday(), 0) + return true + } + else -> return false } } @@ -78,12 +89,14 @@ class ListHabitsSelectionMenu @Inject constructor( val itemColor = menu.findItem(R.id.action_color) val itemArchive = menu.findItem(R.id.action_archive_habit) val itemUnarchive = menu.findItem(R.id.action_unarchive_habit) + val itemNotify = menu.findItem(R.id.action_notify) itemColor.isVisible = true itemEdit.isVisible = behavior.canEdit() itemArchive.isVisible = behavior.canArchive() itemUnarchive.isVisible = behavior.canUnarchive() setTitle(Integer.toString(listAdapter.selected.size)) + itemNotify.isVisible = prefs.isDeveloper return true } diff --git a/uhabits-android/src/main/res/menu/list_habits_selection.xml b/uhabits-android/src/main/res/menu/list_habits_selection.xml index 4f274e39e..0e5cd850a 100644 --- a/uhabits-android/src/main/res/menu/list_habits_selection.xml +++ b/uhabits-android/src/main/res/menu/list_habits_selection.xml @@ -46,4 +46,9 @@ android:title="@string/delete" app:showAsAction="never"/> + + \ No newline at end of file From 0077d35ff9110aa0bc5ea5b3ad2777cc13a07e47 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 14 Nov 2017 23:03:46 -0600 Subject: [PATCH 8/9] Automatically dismiss summary notification --- .../notifications/AndroidNotificationTray.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index 15abc403f..f41c18bca 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -44,8 +44,15 @@ class AndroidNotificationTray private val ringtoneManager: RingtoneManager ) : NotificationTray.SystemTray { + private var active = HashSet() + override fun removeNotification(id: Int) { - NotificationManagerCompat.from(context).cancel(id) + val manager = NotificationManagerCompat.from(context) + manager.cancel(id) + active.remove(id) + + // Clear the group summary notification + if(active.isEmpty()) manager.cancelAll() } override fun showNotification(habit: Habit, @@ -58,6 +65,7 @@ class AndroidNotificationTray notificationManager.notify(Int.MAX_VALUE, summary) val notification = buildNotification(habit, reminderTime, timestamp) notificationManager.notify(notificationId, notification) + active.add(notificationId) } @NonNull @@ -79,8 +87,7 @@ class AndroidNotificationTray val removeRepetitionAction = Action( R.drawable.ic_action_cancel, context.getString(R.string.no), - pendingIntents.removeRepetition(habit) - ) + pendingIntents.removeRepetition(habit)) val wearableBg = decodeResource(context.resources, R.drawable.stripe) From 357f51fd5ee5e1cfb13d5f9ea764c1b918deb73e Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Wed, 6 Dec 2017 21:41:42 -0600 Subject: [PATCH 9/9] SnoozeDelayPickerActivity: Fix timepicker layout --- .../SnoozeDelayPickerActivity.java | 66 +++++++++---------- .../uhabits/receivers/ReminderController.java | 5 +- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java index ab51a7983..03d26a707 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.java @@ -1,41 +1,31 @@ package org.isoron.uhabits.notifications; + +import android.app.*; import android.os.*; import android.support.annotation.*; import android.support.v4.app.*; -import android.support.v7.app.*; import android.text.format.*; import android.view.*; import android.widget.*; -import com.android.datetimepicker.time.*; +import com.android.datetimepicker.time.TimePickerDialog; import org.isoron.uhabits.*; -import org.isoron.uhabits.R; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.receivers.*; import java.util.*; -import butterknife.*; - -import static android.content.ContentUris.*; +import static android.content.ContentUris.parseId; -public class SnoozeDelayPickerActivity extends AppCompatActivity implements AdapterView - .OnItemClickListener +public class SnoozeDelayPickerActivity extends FragmentActivity + implements AdapterView.OnItemClickListener { - public static final String ACTION_ASK_SNOOZE = "org.isoron.uhabits.ACTION_ASK_SNOOZE"; - private Habit habit; private ReminderController reminderController; - @BindArray(R.array.snooze_picker_names) - protected String[] snoozeNames; - - @BindArray(R.array.snooze_picker_values) - protected int[] snoozeValues; - @Override protected void onCreate(@Nullable Bundle bundle) { @@ -49,19 +39,35 @@ public class SnoozeDelayPickerActivity extends AppCompatActivity implements Adap habit = appComponent.getHabitList().getById(parseId(getIntent().getData())); if (habit == null) finish(); - setTheme(R.style.Theme_AppCompat_Light_Dialog_Alert); - ButterKnife.bind(this); + int theme = R.style.Theme_AppCompat_Light_Dialog_Alert; + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(this, theme)) + .setTitle(R.string.select_snooze_delay) + .setItems(R.array.snooze_picker_names, null) + .create(); - ListView listView = new ListView(this); - listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, - snoozeNames)); - listView.setOnItemClickListener(this); - setContentView(listView); + dialog.getListView().setOnItemClickListener(this); + dialog.setOnDismissListener(d -> finish()); + dialog.show(); + } + + private void showTimePicker() + { + final Calendar calendar = Calendar.getInstance(); + TimePickerDialog dialog = TimePickerDialog.newInstance( + (view, hour, minute) -> { + reminderController.onSnoozeTimePicked(habit, hour, minute); + finish(); + }, + calendar.get(Calendar.HOUR_OF_DAY), + calendar.get(Calendar.MINUTE), + DateFormat.is24HourFormat(this)); + dialog.show(getSupportFragmentManager(), "timePicker"); } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { + int[] snoozeValues = getResources().getIntArray(R.array.snooze_picker_values); if (snoozeValues[position] >= 0) { reminderController.onSnoozeDelayPicked(habit, snoozeValues[position]); @@ -70,16 +76,10 @@ public class SnoozeDelayPickerActivity extends AppCompatActivity implements Adap else showTimePicker(); } - private void showTimePicker() + @Override + public void finish() { - final Calendar calendar = Calendar.getInstance(); - int defaultHour = calendar.get(Calendar.HOUR_OF_DAY); - int defaultMinute = calendar.get(Calendar.MINUTE); - TimePickerDialog dialog = TimePickerDialog.newInstance( - (view, hour, minute) -> - reminderController.onSnoozeTimePicked(habit, hour, minute), - defaultHour, defaultMinute, DateFormat.is24HourFormat(this)); - - dialog.show(getSupportFragmentManager(), "timePicker"); + super.finish(); + overridePendingTransition(0, 0); } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java index 0d07a1212..c253064f1 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java @@ -104,9 +104,8 @@ public class ReminderController private void showSnoozeDelayPicker(@NonNull Habit habit, Context context) { context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - Intent intent = new Intent(SnoozeDelayPickerActivity.ACTION_ASK_SNOOZE, - Uri.parse(habit.getUriString()), - context, SnoozeDelayPickerActivity.class); + Intent intent = new Intent(context, SnoozeDelayPickerActivity.class); + intent.setData(Uri.parse(habit.getUriString())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); }