Skip to content

Commit

Permalink
147 customization to snooze (#436)
Browse files Browse the repository at this point in the history
* Add missing strings

* Custom snooze implementation

* Test for custom snooze

* Bump version to v1.15.0
  • Loading branch information
Futsch1 authored Jan 18, 2025
1 parent af64c4f commit cfcae9d
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 53 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ android {
minSdk = 28
multiDexEnabled = true
targetSdk = 35
versionCode = 94
versionName = "1.14.0"
versionCode = 95
versionName = "1.15.0"
base.archivesName = "MedTimer"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down
33 changes: 31 additions & 2 deletions app/src/androidTest/java/com/futsch1/medtimer/NotificationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickD
import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu
import com.adevinta.android.barista.interaction.BaristaSleepInteractions.sleep
import com.adevinta.android.barista.rule.flaky.AllowFlaky
import com.futsch1.medtimer.AndroidTestHelper.MainMenu
import com.futsch1.medtimer.AndroidTestHelper.navigateTo
import org.hamcrest.Matchers.allOf
Expand Down Expand Up @@ -181,7 +180,7 @@ class NotificationTest : BaseTestHelper() {
}

@Test
@AllowFlaky(attempts = 1)
//@AllowFlaky(attempts = 1)
fun variableAmount() {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

Expand Down Expand Up @@ -220,6 +219,35 @@ class NotificationTest : BaseTestHelper() {
assertContains("Test variable amount again")
}

@Test
//@AllowFlaky(attempts = 1)
fun customSnooze() {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

openMenu()
clickOn(R.string.tab_settings)
clickOn(R.string.dismiss_notification_action)
clickOn(R.string.snooze)
clickOn(R.string.snooze_duration)
clickOn(R.string.custom)
pressBack()

AndroidTestHelper.createMedicine("Test med")
AndroidTestHelper.createIntervalReminder("1", 120)

navigateTo(MainMenu.ANALYSIS)
waitAndDismissNotification(device, 2_000)

device.wait(Until.findObject(By.displayId(android.R.id.input)), 2_000)
writeTo(android.R.id.input, "1")
clickDialogPositiveButton()

device.openNotification()
sleep(2_000)
val notification = device.wait(Until.findObject(By.textContains("Test med")), 240_000)
internalAssert(notification != null)
}

private fun getNotificationText(): String {
val s = InstrumentationRegistry.getInstrumentation().targetContext.getString(R.string.taken)
return if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Expand All @@ -229,6 +257,7 @@ class NotificationTest : BaseTestHelper() {
}
}


private fun waitAndDismissNotification(device: UiDevice, timeout: Long = 2000) {
device.openNotification()
var notification = device.wait(Until.findObject(By.textContains("Test med")), timeout)
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/futsch1/medtimer/ActivityIntent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.futsch1.medtimer

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.futsch1.medtimer.overview.customSnoozeDialog
import com.futsch1.medtimer.overview.variableAmountDialog

fun dispatch(activity: AppCompatActivity, intent: Intent) {
if (intent.action == "VARIABLE_AMOUNT") {
variableAmountDialog(activity, intent)
}
if (intent.action == "CUSTOM_SNOOZE") {
customSnoozeDialog(activity, intent)
}
}
5 changes: 2 additions & 3 deletions app/src/main/java/com/futsch1/medtimer/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import androidx.navigation.ui.NavigationUI;
import androidx.preference.PreferenceManager;

import com.futsch1.medtimer.overview.VariableAmount;
import com.google.android.material.bottomnavigation.BottomNavigationView;

import java.util.List;
Expand Down Expand Up @@ -54,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) {

setupNavigation();

new VariableAmount().process(this, this.getIntent());
ActivityIntentKt.dispatch(this, this.getIntent());
}

private void showIntro(SharedPreferences sharedPref) {
Expand Down Expand Up @@ -110,7 +109,7 @@ protected void onResume() {
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
new VariableAmount().process(this, intent);
ActivityIntentKt.dispatch(this, intent);
}

@Override
Expand Down
10 changes: 7 additions & 3 deletions app/src/main/java/com/futsch1/medtimer/helpers/DialogHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import com.google.android.material.textfield.TextInputLayout
class DialogHelper(var context: Context) {
var title: Int? = null
var hint: Int? = null
var initialText: String? = null
var textSink: TextSink? = null
var cancelCallback: CancelCallback? = null
private var initialText: String? = null
private var textSink: TextSink? = null
private var cancelCallback: CancelCallback? = null
private var inputType: Int? = null

fun interface TextSink {
fun consumeText(text: String?)
Expand All @@ -32,6 +33,8 @@ class DialogHelper(var context: Context) {
fun cancelCallback(cancelCallback: CancelCallback) =
apply { this.cancelCallback = cancelCallback }

fun inputType(inputType: Int) = apply { this.inputType = inputType }

fun show() {
val textInputLayout = TextInputLayout(context)
val editText = TextInputEditText(context)
Expand All @@ -46,6 +49,7 @@ class DialogHelper(var context: Context) {
editText.id = android.R.id.input
initialText?.let(editText::setText)
textInputLayout.addView(editText)
inputType?.let(editText::setInputType)

val builder = AlertDialog.Builder(context)
builder.setView(textInputLayout)
Expand Down
42 changes: 42 additions & 0 deletions app/src/main/java/com/futsch1/medtimer/overview/CustomSnooze.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.futsch1.medtimer.overview

import android.content.Intent
import android.text.InputType
import androidx.appcompat.app.AppCompatActivity
import com.futsch1.medtimer.ActivityCodes.EXTRA_NOTIFICATION_ID
import com.futsch1.medtimer.ActivityCodes.EXTRA_REMINDER_EVENT_ID
import com.futsch1.medtimer.ActivityCodes.EXTRA_REMINDER_ID
import com.futsch1.medtimer.R
import com.futsch1.medtimer.helpers.DialogHelper
import com.futsch1.medtimer.reminders.NotificationAction
import com.futsch1.medtimer.reminders.ReminderProcessor

fun customSnoozeDialog(activity: AppCompatActivity, intent: Intent) {
val reminderId: Int = intent.getIntExtra(EXTRA_REMINDER_ID, -1)
val reminderEventId: Int = intent.getIntExtra(EXTRA_REMINDER_EVENT_ID, -1)
val notificationId: Int = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)

// Cancel a potential repeat alarm
NotificationAction.cancelPendingAlarms(activity, reminderEventId)

DialogHelper(activity)
.title(R.string.snooze_duration)
.hint(R.string.minutes)
.initialText("")
.inputType(InputType.TYPE_NUMBER_FLAG_SIGNED)
.textSink { snoozeTime: String? ->
val snoozeTimeInt = snoozeTime?.toIntOrNull()
if (snoozeTimeInt != null) {
val snooze = ReminderProcessor.getSnoozeIntent(
activity,
reminderId,
reminderEventId,
notificationId,
snoozeTimeInt
)
activity.sendBroadcast(snooze, "com.futsch1.medtimer.NOTIFICATION_PROCESSED")
}
}
.show()

}
82 changes: 41 additions & 41 deletions app/src/main/java/com/futsch1/medtimer/overview/VariableAmount.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,14 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.time.Instant

class VariableAmount(private val dispatcher: CoroutineDispatcher = Dispatchers.IO) {
fun process(activity: AppCompatActivity, intent: Intent) {
val reminderEventId = intent.getIntExtra(EXTRA_REMINDER_EVENT_ID, -1)
if (reminderEventId != -1) {
showDialogToEnterAmount(activity, reminderEventId, intent.getStringExtra(EXTRA_AMOUNT))
}
}

private fun showDialogToEnterAmount(
activity: AppCompatActivity,
reminderEventId: Int,
amount: String?
) {
fun variableAmountDialog(
activity: AppCompatActivity,
intent: Intent,
dispatcher: CoroutineDispatcher = Dispatchers.IO
) {
val reminderEventId = intent.getIntExtra(EXTRA_REMINDER_EVENT_ID, -1)
val amount = intent.getStringExtra(EXTRA_AMOUNT)
if (reminderEventId != -1) {
DialogHelper(activity)
.title(R.string.log_additional_dose)
.hint(R.string.dosage)
Expand All @@ -36,39 +31,44 @@ class VariableAmount(private val dispatcher: CoroutineDispatcher = Dispatchers.I
updateReminderEvent(
activity,
reminderEventId,
amountLocal!!
amountLocal!!,
dispatcher
)
}
.cancelCallback { touchReminderEvent(activity, reminderEventId) }
.cancelCallback { touchReminderEvent(activity, reminderEventId, dispatcher) }
.show()

}
}

private fun touchReminderEvent(activity: AppCompatActivity, reminderEventId: Int) {
activity.lifecycleScope.launch(dispatcher) {
val repository = MedicineRepository(activity.application)
val reminderEvent = repository.getReminderEvent(reminderEventId)
reminderEvent?.processedTimestamp = Instant.now().epochSecond
repository.updateReminderEvent(reminderEvent)
}
private fun touchReminderEvent(
activity: AppCompatActivity,
reminderEventId: Int,
dispatcher: CoroutineDispatcher
) {
activity.lifecycleScope.launch(dispatcher) {
val repository = MedicineRepository(activity.application)
val reminderEvent = repository.getReminderEvent(reminderEventId)
reminderEvent?.processedTimestamp = Instant.now().epochSecond
repository.updateReminderEvent(reminderEvent)
}
}

private fun updateReminderEvent(
activity: AppCompatActivity,
reminderEventId: Int,
amount: String
) {
activity.lifecycleScope.launch(dispatcher) {
val repository = MedicineRepository(activity.application)
val reminderEvent = repository.getReminderEvent(reminderEventId)
reminderEvent?.amount = amount
NotificationAction.processReminderEvent(
activity,
reminderEventId,
ReminderEvent.ReminderStatus.TAKEN,
reminderEvent!!,
repository
)
}
private fun updateReminderEvent(
activity: AppCompatActivity,
reminderEventId: Int,
amount: String,
dispatcher: CoroutineDispatcher
) {
activity.lifecycleScope.launch(dispatcher) {
val repository = MedicineRepository(activity.application)
val reminderEvent = repository.getReminderEvent(reminderEventId)
reminderEvent?.amount = amount
NotificationAction.processReminderEvent(
activity,
reminderEventId,
ReminderEvent.ReminderStatus.TAKEN,
reminderEvent!!,
repository
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ private void buildActions(NotificationCompat.Builder builder, int notificationId
String dismissNotificationAction = defaultSharedPreferences.getString("dismiss_notification_action", "0");
int snoozeTime = Integer.parseInt(defaultSharedPreferences.getString("snooze_duration", "15"));

Intent snooze = ReminderProcessor.getSnoozeIntent(context, reminder.reminderId, reminderEventId, notificationId, snoozeTime);
PendingIntent pendingSnooze = PendingIntent.getBroadcast(context, notificationId, snooze, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingSnooze = getSnoozePendingIntent(context, reminder.reminderId, reminderEventId, notificationId, snoozeTime);

Intent notifyDismissed = ReminderProcessor.getDismissedActionIntent(context, reminderEventId);
PendingIntent pendingDismissed = PendingIntent.getBroadcast(context, notificationId, notifyDismissed, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
Expand All @@ -121,6 +120,16 @@ private void buildActions(NotificationCompat.Builder builder, int notificationId
}
}

private PendingIntent getSnoozePendingIntent(Context context, int reminderId, int reminderEventId, int notificationId, int snoozeTime) {
if (snoozeTime == -1) {
Intent snooze = ReminderProcessor.getCustomSnoozeActionIntent(context, reminderId, reminderEventId, notificationId);
return PendingIntent.getActivity(context, notificationId, snooze, PendingIntent.FLAG_IMMUTABLE);
} else {
Intent snooze = ReminderProcessor.getSnoozeIntent(context, reminderId, reminderEventId, notificationId, snoozeTime);
return PendingIntent.getBroadcast(context, notificationId, snooze, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
}
}

private PendingIntent getTakenPendingIntent(int notificationId, int reminderEventId, Reminder reminder) {
if (reminder.variableAmount) {
Intent notifyTaken = ReminderProcessor.getVariableAmountActionIntent(context, reminderEventId, reminder.amount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ public static Intent getVariableAmountActionIntent(Context context, int reminder
return actionIntent;
}

public static Intent getCustomSnoozeActionIntent(Context context, int reminderId, int reminderEventId, int notificationId) {
Intent actionIntent = new Intent(context, MainActivity.class);
actionIntent.setAction("CUSTOM_SNOOZE");
actionIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
actionIntent.putExtra(EXTRA_REMINDER_ID, reminderId);
actionIntent.putExtra(EXTRA_REMINDER_EVENT_ID, reminderEventId);
actionIntent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
return actionIntent;
}

@Override
public void onReceive(Context context, Intent intent) {
WorkManager workManager = WorkManagerAccess.getWorkManager(context);
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/res/values-ta/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,16 @@
<string name="refill_size">மறு நிரப்பல் அளவு</string>
<string name="refill_now">இப்போது மீண்டும் நிரப்பவும்</string>
<string name="variable_amount">எடுக்கும்போது அளவை உள்ளிடவும்</string>
<plurals name="minutes">
<item quantity="one">நிமிடம்</item>
<item quantity="other">நிமிடங்கள்</item>
</plurals>
<plurals name="hours">
<item quantity="one">மணிநேரம்</item>
<item quantity="other">மணிநேரங்கள்</item>
</plurals>
<plurals name="days">
<item quantity="one">நாள்</item>
<item quantity="other">நாட்கள்</item>
</plurals>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,15 @@
<item>@string/minutes_15</item>
<item>@string/minutes_30</item>
<item>@string/minutes_60</item>
<item>@string/custom</item>
</string-array>
<string-array name="snooze_duration_values">
<item>5</item>
<item>10</item>
<item>15</item>
<item>30</item>
<item>60</item>
<item>-1</item>
</string-array>
<string-array name="days">
<item>@string/monday</item>
Expand Down

0 comments on commit cfcae9d

Please sign in to comment.