Skip to content

Commit ac37bf7

Browse files
author
default-student
committed
snooze button
1 parent d417462 commit ac37bf7

5 files changed

Lines changed: 86 additions & 23 deletions

File tree

app/src/main/java/it/niedermann/nextcloud/deck/reminders/DueReminderActivity.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
5555
}
5656

5757
binding.dismiss.setOnClickListener((v) -> finish());
58+
binding.snooze.setOnClickListener((v) -> snooze());
5859
binding.openCard.setOnClickListener((v) -> openCard());
5960
binding.markComplete.setOnClickListener((v) -> markComplete());
6061

@@ -142,6 +143,18 @@ private void markComplete() {
142143
});
143144
}
144145

146+
private void snooze() {
147+
setLoading(true);
148+
final var appContext = getApplicationContext();
149+
ExecutorServiceProvider.getLinkedBlockingQueueExecutor().submit(() -> {
150+
DueReminderScheduler.snooze(appContext, cardLocalId);
151+
runOnUiThread(() -> {
152+
Toast.makeText(this, R.string.local_due_reminder_snoozed, Toast.LENGTH_SHORT).show();
153+
finish();
154+
});
155+
});
156+
}
157+
145158
private void openCard() {
146159
if (account == null || board == null) {
147160
return;
@@ -155,6 +168,7 @@ private void setLoading(boolean loading) {
155168
binding.progress.setVisibility(loading ? View.VISIBLE : View.GONE);
156169
binding.markComplete.setEnabled(!loading);
157170
binding.openCard.setEnabled(!loading && account != null && board != null);
171+
binding.snooze.setEnabled(!loading);
158172
binding.dismiss.setEnabled(!loading);
159173
}
160174
}

app/src/main/java/it/niedermann/nextcloud/deck/reminders/DueReminderReceiver.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class DueReminderReceiver extends BroadcastReceiver {
1313

1414
static final String ACTION_SHOW_REMINDER = "it.niedermann.nextcloud.deck.reminders.SHOW_REMINDER";
1515
static final String ACTION_MARK_COMPLETE = "it.niedermann.nextcloud.deck.reminders.MARK_COMPLETE";
16+
static final String ACTION_SNOOZE = "it.niedermann.nextcloud.deck.reminders.SNOOZE";
1617
static final String EXTRA_CARD_LOCAL_ID = "cardLocalId";
1718

1819
@Override
@@ -36,6 +37,8 @@ public void onReceive(Context context, Intent intent) {
3637
try {
3738
if (ACTION_MARK_COMPLETE.equals(action)) {
3839
DueReminderScheduler.markComplete(appContext, cardLocalId);
40+
} else if (ACTION_SNOOZE.equals(action)) {
41+
DueReminderScheduler.snooze(appContext, cardLocalId);
3942
} else {
4043
DueReminderScheduler.showReminder(appContext, cardLocalId);
4144
}

app/src/main/java/it/niedermann/nextcloud/deck/reminders/DueReminderScheduler.java

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
public final class DueReminderScheduler {
4343

44+
private static final int SNOOZE_MINUTES = 5;
4445
static final String CHANNEL_ID = "due_reminders";
4546
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
4647

@@ -84,27 +85,7 @@ public static void scheduleCard(@NonNull Context context, @Nullable Card card) {
8485
return;
8586
}
8687

87-
final var alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
88-
if (alarmManager == null) {
89-
DeckLog.warn("Could not schedule due reminder because AlarmManager is unavailable.");
90-
return;
91-
}
92-
93-
final long dueAtMillis = card.getDueDate().toEpochMilli();
94-
final PendingIntent pendingIntent = createReminderPendingIntent(context, card.getLocalId());
95-
96-
if (canScheduleExactAlarms(alarmManager)) {
97-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
98-
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dueAtMillis, pendingIntent);
99-
} else {
100-
alarmManager.setExact(AlarmManager.RTC_WAKEUP, dueAtMillis, pendingIntent);
101-
}
102-
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
103-
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dueAtMillis, pendingIntent);
104-
} else {
105-
alarmManager.set(AlarmManager.RTC_WAKEUP, dueAtMillis, pendingIntent);
106-
}
107-
88+
scheduleAt(context, card.getLocalId(), card.getDueDate().toEpochMilli());
10889
DeckLog.info("Scheduled due reminder for card", card.getLocalId(), "at", card.getDueDate());
10990
}
11091

@@ -144,6 +125,7 @@ public static void showReminder(@NonNull Context context, long cardLocalId) {
144125
final PendingIntent openCardPendingIntent = createOpenCardPendingIntent(context, account, board, cardLocalId);
145126
final PendingIntent fullScreenPendingIntent = createFullScreenPendingIntent(context, cardLocalId);
146127
final PendingIntent completePendingIntent = createCompletePendingIntent(context, cardLocalId);
128+
final PendingIntent snoozePendingIntent = createSnoozePendingIntent(context, cardLocalId);
147129

148130
final String title = context.getString(R.string.local_due_reminder_notification_title, safeTitle(fullCard.getCard()));
149131
final String dueAt = fullCard.getCard().getDueDate()
@@ -162,6 +144,7 @@ public static void showReminder(@NonNull Context context, long cardLocalId) {
162144
.setContentIntent(openCardPendingIntent)
163145
.setFullScreenIntent(fullScreenPendingIntent, true)
164146
.addAction(R.drawable.ic_outline_check_circle_24, context.getString(R.string.local_due_reminder_mark_complete), completePendingIntent)
147+
.addAction(R.drawable.ic_time_24, context.getString(R.string.local_due_reminder_snooze), snoozePendingIntent)
165148
.setAutoCancel(true)
166149
.build();
167150

@@ -174,6 +157,24 @@ public static void showReminder(@NonNull Context context, long cardLocalId) {
174157
}
175158
}
176159

160+
public static void snooze(@NonNull Context context, long cardLocalId) {
161+
if (!isEnabled(context)) {
162+
return;
163+
}
164+
165+
final var dataBaseAdapter = new DataBaseAdapter(context.getApplicationContext());
166+
final FullCard fullCard = dataBaseAdapter.getFullCardByLocalIdDirectly(cardLocalId);
167+
if (fullCard == null || !shouldNotify(fullCard.getCard())) {
168+
DeckLog.info("Skipping snooze for stale card", cardLocalId);
169+
return;
170+
}
171+
172+
final long snoozedUntilMillis = Instant.now().plusSeconds(SNOOZE_MINUTES * 60L).toEpochMilli();
173+
scheduleAt(context, cardLocalId, snoozedUntilMillis);
174+
NotificationManagerCompat.from(context).cancel(notificationId(cardLocalId));
175+
DeckLog.info("Snoozed due reminder for card", cardLocalId, "until", Instant.ofEpochMilli(snoozedUntilMillis));
176+
}
177+
177178
public static void markComplete(@NonNull Context context, long cardLocalId) {
178179
final var dataBaseAdapter = new DataBaseAdapter(context.getApplicationContext());
179180
if (dataBaseAdapter.markCardDoneDirectly(cardLocalId, Instant.now())) {
@@ -200,6 +201,28 @@ private static boolean canScheduleExactAlarms(@NonNull AlarmManager alarmManager
200201
return Build.VERSION.SDK_INT < Build.VERSION_CODES.S || alarmManager.canScheduleExactAlarms();
201202
}
202203

204+
private static void scheduleAt(@NonNull Context context, long cardLocalId, long triggerAtMillis) {
205+
final var alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
206+
if (alarmManager == null) {
207+
DeckLog.warn("Could not schedule due reminder because AlarmManager is unavailable.");
208+
return;
209+
}
210+
211+
final PendingIntent pendingIntent = createReminderPendingIntent(context, cardLocalId);
212+
213+
if (canScheduleExactAlarms(alarmManager)) {
214+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
215+
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
216+
} else {
217+
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
218+
}
219+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
220+
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
221+
} else {
222+
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
223+
}
224+
}
225+
203226
private static boolean shouldSchedule(@NonNull Card card) {
204227
return shouldNotify(card) && card.getDueDate().isAfter(Instant.now());
205228
}
@@ -249,6 +272,15 @@ private static PendingIntent createCompletePendingIntent(@NonNull Context contex
249272
);
250273
}
251274

275+
private static PendingIntent createSnoozePendingIntent(@NonNull Context context, long cardLocalId) {
276+
return PendingIntent.getBroadcast(
277+
context,
278+
notificationId(cardLocalId) + 300_000,
279+
DueReminderReceiver.createIntent(context, DueReminderReceiver.ACTION_SNOOZE, cardLocalId),
280+
FLAG_IMMUTABLE | FLAG_CANCEL_CURRENT
281+
);
282+
}
283+
252284
private static PendingIntent createFullScreenPendingIntent(@NonNull Context context, long cardLocalId) {
253285
return PendingIntent.getActivity(
254286
context,

app/src/main/res/layout/activity_due_reminder.xml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,27 @@
147147
style="@style/Widget.Material3.Button.OutlinedButton"
148148
android:layout_width="0dp"
149149
android:layout_height="52dp"
150-
android:layout_marginEnd="6dp"
150+
android:layout_marginEnd="4dp"
151151
android:layout_weight="1"
152152
android:text="@string/local_due_reminder_open_card" />
153153

154+
<com.google.android.material.button.MaterialButton
155+
android:id="@+id/snooze"
156+
style="@style/Widget.Material3.Button.OutlinedButton"
157+
android:layout_width="0dp"
158+
android:layout_height="52dp"
159+
android:layout_marginStart="4dp"
160+
android:layout_marginEnd="4dp"
161+
android:layout_weight="1"
162+
android:text="@string/local_due_reminder_snooze_short"
163+
app:icon="@drawable/ic_time_24" />
164+
154165
<com.google.android.material.button.MaterialButton
155166
android:id="@+id/dismiss"
156167
style="@style/Widget.Material3.Button.TextButton"
157168
android:layout_width="0dp"
158169
android:layout_height="52dp"
159-
android:layout_marginStart="6dp"
170+
android:layout_marginStart="4dp"
160171
android:layout_weight="1"
161172
android:text="@string/local_due_reminder_dismiss" />
162173
</LinearLayout>

app/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,13 @@
201201
<string name="local_due_reminder_notification_text">%1$s · %2$s · %3$s</string>
202202
<string name="local_due_reminder_fullscreen_title">Due reminder</string>
203203
<string name="local_due_reminder_mark_complete">Mark complete</string>
204+
<string name="local_due_reminder_snooze">Snooze 5 min</string>
205+
<string name="local_due_reminder_snooze_short">Snooze</string>
204206
<string name="local_due_reminder_open_card">Open card</string>
205207
<string name="local_due_reminder_dismiss">Dismiss</string>
206208
<string name="local_due_reminder_account">%1$s on %2$s</string>
207209
<string name="local_due_reminder_completed">Card marked complete</string>
210+
<string name="local_due_reminder_snoozed">Snoozed for 5 minutes</string>
208211
<string name="local_due_reminder_unavailable">This reminder is no longer available</string>
209212
<string name="local_due_reminder_untitled_card">Untitled card</string>
210213

0 commit comments

Comments
 (0)