Repository: Futsch1/medTimer (language: kotlin)

Issue:
same day reminder
I can not figure out how to add an reminder to start the same day. Next reminder is always set to next day.
Show all medicines due in a day
The "next reminder" section could be more useful if it listed all the medications needed in a day.

As an example, I have to take pills every two days and patches every four days. On overlap days I don't have a set order for pills and patches but I set the reminder for both at 10pm since I have to take/change them at night (actually the precise time doesn't even matter).

Right now it seems that patches have a priority over pills, so if I take pills beforehand I have to wait until I apply my patch to check that as done and then the pills reminder is next so I also check that as done. Since it is not guaranteed I take both at the same time I could miss marking either or both of them for that day, just because I need to do patches first and then I forget to check the app again when I eventually come to do them (because my brain will tell me I took my meds and also that I already checked the app)

Therefore, I think that in the Overview it'd be better to list all the medications that need to be taken on that day, along with the hour and the "taken/skipped" buttons instead of just showing one entry.

Edit: There's a thing I missed in my use case, that is, I usually take my medications before 10pm so the notifications would usually arrive "late"; that is because I use the app to track past medications more than to remind me of taking them.


Discussion hints:
This is how it is implemented right now: freshly created reminders will first trigger on the next day. So you'd have to wait for one day.

Is this an issue for you?
Ok then.

Well in my case I had something to take in the same day, but it is not a big deal really. 

In this case, I won't do any changes.


Pull request: Overview show all due
fixes #122 
fixes #132 

Test command: ./gradlew :app:testDebugUnitTest --tests "com.futsch1.medtimer.ReminderSchedulerDaysUnitTest" --tests "com.futsch1.medtimer.ReminderSchedulerUnitTest"

Fix patch:
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 18bf35e59..296b9a2be 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -17,8 +17,8 @@ android {
         applicationId = "com.futsch1.medtimer"
         minSdk = 33
         targetSdk = 34
-        versionCode = 48
-        versionName = "1.8.4"
+        versionCode = 50
+        versionName = "1.8.5"
         setProperty("archivesBaseName", "MedTimer")
 
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
diff --git a/app/src/main/java/com/futsch1/medtimer/ActivityCodes.java b/app/src/main/java/com/futsch1/medtimer/ActivityCodes.java
index 1c701444f..0395deedc 100644
--- a/app/src/main/java/com/futsch1/medtimer/ActivityCodes.java
+++ b/app/src/main/java/com/futsch1/medtimer/ActivityCodes.java
@@ -3,12 +3,10 @@
 public class ActivityCodes {
     public static final String EXTRA_REMINDER_EVENT_ID = "com.futsch1.medTimer.REMINDER_EVENT_ID";
     public static final String EXTRA_REMINDER_ID = "com.futsch1.medTimer.REMINDER_ID";
-    public static final String EXTRA_REMINDER_TIME = "com.futsch1.medTimer.REMINDER_TIME";
     public static final String EXTRA_SNOOZE_TIME = "com.futsch1.medTimer.SNOOZE_TIME";
     public static final String EXTRA_NOTIFICATION_ID = "com.futsch1.medTimer.NOTIFICATION_ID";
 
     public static final String REMINDER_ACTION = "com.futsch1.medTimer.REMINDER_ACTION";
-    public static final String NEXT_REMINDER_ACTION = "com.futsch1.medTimer.NEXT_REMINDER_ACTION";
     public static final String RESCHEDULE_ACTION = "com.futsch1.medTimer.RESCHEDULE_ACTION";
     public static final String DISMISSED_ACTION = "com.futsch1.medTimer.DISMISSED_ACTION";
     public static final String TAKEN_ACTION = "com.futsch1.medTimer.TAKEN_ACTION";
diff --git a/app/src/main/java/com/futsch1/medtimer/NextRemindersViewModel.java b/app/src/main/java/com/futsch1/medtimer/NextRemindersViewModel.java
new file mode 100644
index 000000000..18995054c
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/NextRemindersViewModel.java
@@ -0,0 +1,21 @@
+package com.futsch1.medtimer;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+import java.util.List;
+
+public class NextRemindersViewModel extends ViewModel {
+
+    private final MutableLiveData<List<ScheduledReminder>> scheduledReminders = new MutableLiveData<>();
+
+    public LiveData<List<ScheduledReminder>> getScheduledReminders() {
+        return scheduledReminders;
+    }
+
+    public void setScheduledReminders(List<ScheduledReminder> scheduledReminders) {
+        this.scheduledReminders.setValue(scheduledReminders);
+    }
+
+}
diff --git a/app/src/main/java/com/futsch1/medtimer/ScheduledReminder.java b/app/src/main/java/com/futsch1/medtimer/ScheduledReminder.java
new file mode 100644
index 000000000..214004517
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/ScheduledReminder.java
@@ -0,0 +1,10 @@
+package com.futsch1.medtimer;
+
+import com.futsch1.medtimer.database.Medicine;
+import com.futsch1.medtimer.database.Reminder;
+
+import java.time.Instant;
+
+public record ScheduledReminder(Medicine medicine, Reminder reminder, Instant timestamp) {
+
+}
diff --git a/app/src/main/java/com/futsch1/medtimer/medicine/EditMedicineFragment.java b/app/src/main/java/com/futsch1/medtimer/medicine/EditMedicineFragment.java
index 988b6289c..6a6e78249 100644
--- a/app/src/main/java/com/futsch1/medtimer/medicine/EditMedicineFragment.java
+++ b/app/src/main/java/com/futsch1/medtimer/medicine/EditMedicineFragment.java
@@ -96,11 +96,13 @@ public void onResume() {
     public void onDestroy() {
         super.onDestroy();
 
-        String word = editMedicineName.getText().toString();
-        Medicine medicine = new Medicine(word, medicineId);
-        medicine.useColor = enableColor.isChecked();
-        medicine.color = color;
-        medicineViewModel.updateMedicine(medicine);
+        if (editMedicineName != null && enableColor != null) {
+            String word = editMedicineName.getText().toString();
+            Medicine medicine = new Medicine(word, medicineId);
+            medicine.useColor = enableColor.isChecked();
+            medicine.color = color;
+            medicineViewModel.updateMedicine(medicine);
+        }
 
         RecyclerView recyclerView = fragmentEditMedicine.findViewById(R.id.reminderList);
         for (int i = 0; i < recyclerView.getChildCount(); i++) {
diff --git a/app/src/main/java/com/futsch1/medtimer/overview/NextReminderListener.java b/app/src/main/java/com/futsch1/medtimer/overview/NextReminderListener.java
deleted file mode 100644
index d83deced5..000000000
--- a/app/src/main/java/com/futsch1/medtimer/overview/NextReminderListener.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.futsch1.medtimer.overview;
-
-import static com.futsch1.medtimer.ActivityCodes.EXTRA_REMINDER_ID;
-import static com.futsch1.medtimer.ActivityCodes.EXTRA_REMINDER_TIME;
-import static com.futsch1.medtimer.ActivityCodes.NEXT_REMINDER_ACTION;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.util.Log;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-
-import com.futsch1.medtimer.MedicineViewModel;
-import com.futsch1.medtimer.R;
-import com.futsch1.medtimer.database.Medicine;
-import com.futsch1.medtimer.database.Reminder;
-import com.futsch1.medtimer.database.ReminderEvent;
-import com.futsch1.medtimer.reminders.ReminderProcessor;
-import com.futsch1.medtimer.reminders.ReminderWork;
-
-import java.time.Instant;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
-
-public class NextReminderListener extends BroadcastReceiver {
-    private final TextView nextReminder;
-    private final MedicineViewModel medicineViewModel;
-
-    private final HandlerThread thread;
-    private final NextReminderIsTodayCallback nextReminderIsTodayCallback;
-    private Reminder reminder;
-    private Medicine medicine;
-
-    public NextReminderListener(TextView nextReminder, NextReminderIsTodayCallback nextReminderIsTodayCallback, MedicineViewModel medicineViewModel) {
-        this.nextReminder = nextReminder;
-        this.nextReminderIsTodayCallback = nextReminderIsTodayCallback;
-        this.medicineViewModel = medicineViewModel;
-        this.thread = new HandlerThread("UpdateNextReminder");
-        this.thread.start();
-    }
-
-    public static void sendNextReminder(@NonNull Context context, int reminderId, Instant timestamp) {
-        Intent nextReminderIntent = new Intent(NEXT_REMINDER_ACTION);
-        nextReminderIntent.putExtra(EXTRA_REMINDER_ID, reminderId);
-        nextReminderIntent.putExtra(EXTRA_REMINDER_TIME, timestamp);
-        context.sendBroadcast(nextReminderIntent);
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Log.d("ReminderListener", "Next reminder received");
-        final Handler handler = new Handler(thread.getLooper());
-        handler.post(() -> receiveNextReminderIntent(context, intent));
-    }
-
-    private void receiveNextReminderIntent(Context context, Intent intent) {
-        int reminderId = intent.getIntExtra(EXTRA_REMINDER_ID, 0);
-        Instant timestamp = intent.getSerializableExtra(EXTRA_REMINDER_TIME, Instant.class);
-        if (reminderId > 0 && timestamp != null) {
-            reminder = medicineViewModel.getReminder(reminderId);
-            if (reminder != null) {
-                medicine = medicineViewModel.getMedicine(reminder.medicineRelId);
-                ZonedDateTime reminderTime = timestamp.atZone(ZoneId.systemDefault());
-                reportIfNextReminderIsToday(reminderTime);
-                String nextTime = reminderTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT));
-                final Handler mainHandler = new Handler(Looper.getMainLooper());
-                mainHandler.post(() -> setNextReminderText(context, reminder, medicine, nextTime));
-            }
-        }
-    }
-
-    private void reportIfNextReminderIsToday(ZonedDateTime reminderTime) {
-        nextReminderIsTodayCallback.nextReminderIsToday(reminderTime.getDayOfMonth() == ZonedDateTime.now().getDayOfMonth() &&
-                reminderTime.getMonth() == ZonedDateTime.now().getMonth());
-    }
-
-    private void setNextReminderText(Context context, Reminder reminder, Medicine medicine, String nextTime) {
-        if (reminder != null && medicine != null) {
-            nextReminder.setText(context.getString(R.string.reminder_event, reminder.amount, medicine.name, nextTime));
-            nextReminder.setCompoundDrawables(null, null, null, null);
-        }
-    }
-
-    public void processFutureReminder(boolean taken) {
-        Handler handler = new Handler(thread.getLooper());
-        handler.post(() -> {
-            ReminderEvent reminderEvent = ReminderWork.buildReminderEvent(medicine, reminder);
-            if (reminderEvent != null) {
-                reminderEvent.status = taken ? ReminderEvent.ReminderStatus.TAKEN : ReminderEvent.ReminderStatus.SKIPPED;
-                reminderEvent.processedTimestamp = Instant.now().getEpochSecond();
-                medicineViewModel.medicineRepository.insertReminderEvent(reminderEvent);
-                ReminderProcessor.requestReschedule(nextReminder.getContext());
-            }
-        });
-
-    }
-
-    public void stop() {
-        thread.quitSafely();
-    }
-
-    public interface NextReminderIsTodayCallback {
-        void nextReminderIsToday(boolean isToday);
-    }
-}
diff --git a/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewAdapter.java b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewAdapter.java
new file mode 100644
index 000000000..d6a32b933
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewAdapter.java
@@ -0,0 +1,56 @@
+package com.futsch1.medtimer.overview;
+
+import android.os.HandlerThread;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.ListAdapter;
+
+import com.futsch1.medtimer.MedicineViewModel;
+import com.futsch1.medtimer.ScheduledReminder;
+
+public class NextRemindersViewAdapter extends ListAdapter<ScheduledReminder, NextRemindersViewHolder> {
+
+    private final HandlerThread thread;
+    private final MedicineViewModel medicineViewModel;
+
+    public NextRemindersViewAdapter(@NonNull DiffUtil.ItemCallback<ScheduledReminder> diffCallback, MedicineViewModel medicineViewModel) {
+        super(diffCallback);
+        setHasStableIds(true);
+        this.medicineViewModel = medicineViewModel;
+        this.thread = new HandlerThread("UpdateNextReminder");
+        this.thread.start();
+    }
+
+    @NonNull
+    @Override
+    public NextRemindersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        return NextRemindersViewHolder.create(parent);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull NextRemindersViewHolder holder, final int position) {
+        ScheduledReminder current = getItem(position);
+        holder.bind(current, thread.getLooper(), medicineViewModel);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).reminder().reminderId;
+    }
+
+    public static class ScheduledReminderDiff extends DiffUtil.ItemCallback<ScheduledReminder> {
+
+        @Override
+        public boolean areItemsTheSame(@NonNull ScheduledReminder oldItem, @NonNull ScheduledReminder newItem) {
+            return oldItem.reminder().reminderId == newItem.reminder().reminderId;
+        }
+
+        @Override
+        public boolean areContentsTheSame(@NonNull ScheduledReminder oldItem, @NonNull ScheduledReminder newItem) {
+            return oldItem.reminder().reminderId == newItem.reminder().reminderId && oldItem.timestamp().equals(newItem.timestamp()) &&
+                    oldItem.reminder().instructions.equals(newItem.reminder().instructions);
+        }
+    }
+}
diff --git a/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java
new file mode 100644
index 000000000..ff2cb7349
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java
@@ -0,0 +1,78 @@
+package com.futsch1.medtimer.overview;
+
+import static android.text.format.DateUtils.isToday;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.futsch1.medtimer.MedicineViewModel;
+import com.futsch1.medtimer.R;
+import com.futsch1.medtimer.ScheduledReminder;
+import com.futsch1.medtimer.database.ReminderEvent;
+import com.futsch1.medtimer.helpers.ViewColorHelper;
+import com.futsch1.medtimer.reminders.ReminderProcessor;
+import com.futsch1.medtimer.reminders.ReminderWork;
+import com.google.android.material.card.MaterialCardView;
+import com.google.android.material.chip.Chip;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Collections;
+
+public class NextRemindersViewHolder extends RecyclerView.ViewHolder {
+    private final TextView nextReminderText;
+
+    private NextRemindersViewHolder(View itemView) {
+        super(itemView);
+        nextReminderText = itemView.findViewById(R.id.nextReminderText);
+    }
+
+    static NextRemindersViewHolder create(ViewGroup parent) {
+        View view = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.fragment_next_reminder, parent, false);
+        return new NextRemindersViewHolder(view);
+    }
+
+    public void bind(ScheduledReminder scheduledReminder, Looper looper, MedicineViewModel medicineViewModel) {
+        Chip takenNow = itemView.findViewById(R.id.takenNow);
+        Chip skippedNow = itemView.findViewById(R.id.skippedNow);
+        takenNow.setOnClickListener(v -> processFutureReminder(scheduledReminder, true, looper, medicineViewModel));
+        skippedNow.setOnClickListener(v -> processFutureReminder(scheduledReminder, false, looper, medicineViewModel));
+
+        ZonedDateTime reminderTime = scheduledReminder.timestamp().atZone(ZoneId.systemDefault());
+        String nextTime = reminderTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT));
+        nextReminderText.setText(nextReminderText.getContext().getString(R.string.reminder_event, scheduledReminder.reminder().amount, scheduledReminder.medicine().name, nextTime));
+
+        boolean isToday = isToday(scheduledReminder.timestamp().toEpochMilli());
+        takenNow.setVisibility(isToday ? View.VISIBLE : View.GONE);
+        skippedNow.setVisibility(isToday ? View.VISIBLE : View.GONE);
+
+        if (scheduledReminder.medicine().useColor) {
+            ViewColorHelper.setCardBackground((MaterialCardView) itemView, Collections.singletonList(nextReminderText), scheduledReminder.medicine().color);
+        } else {
+            ViewColorHelper.setDefaultColors((MaterialCardView) itemView, Collections.singletonList(nextReminderText));
+        }
+    }
+
+    private void processFutureReminder(ScheduledReminder scheduledReminder, boolean taken, Looper looper, MedicineViewModel medicineViewModel) {
+        Handler handler = new Handler(looper);
+        handler.post(() -> {
+            ReminderEvent reminderEvent = ReminderWork.buildReminderEvent(scheduledReminder.medicine(), scheduledReminder.reminder());
+            if (reminderEvent != null) {
+                reminderEvent.status = taken ? ReminderEvent.ReminderStatus.TAKEN : ReminderEvent.ReminderStatus.SKIPPED;
+                reminderEvent.processedTimestamp = Instant.now().getEpochSecond();
+                medicineViewModel.medicineRepository.insertReminderEvent(reminderEvent);
+                ReminderProcessor.requestReschedule(nextReminderText.getContext());
+            }
+        });
+    }
+}
diff --git a/app/src/main/java/com/futsch1/medtimer/overview/OverviewFragment.java b/app/src/main/java/com/futsch1/medtimer/overview/OverviewFragment.java
index f6a287989..b8f9adade 100644
--- a/app/src/main/java/com/futsch1/medtimer/overview/OverviewFragment.java
+++ b/app/src/main/java/com/futsch1/medtimer/overview/OverviewFragment.java
@@ -1,19 +1,16 @@
 package com.futsch1.medtimer.overview;
 
-import static com.futsch1.medtimer.ActivityCodes.NEXT_REMINDER_ACTION;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.Looper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.LinearLayout;
 
 import androidx.annotation.NonNull;
 import androidx.fragment.app.Fragment;
@@ -27,22 +24,35 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.futsch1.medtimer.MedicineViewModel;
+import com.futsch1.medtimer.NextRemindersViewModel;
 import com.futsch1.medtimer.R;
+import com.futsch1.medtimer.ScheduledReminder;
+import com.futsch1.medtimer.database.MedicineWithReminders;
 import com.futsch1.medtimer.database.ReminderEvent;
 import com.futsch1.medtimer.helpers.SwipeHelper;
 import com.futsch1.medtimer.reminders.ReminderProcessor;
+import com.futsch1.medtimer.reminders.scheduling.ReminderScheduler;
+import com.google.android.material.button.MaterialButton;
+import com.google.android.material.card.MaterialCardView;
 
 import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.util.List;
 
 public class OverviewFragment extends Fragment {
-    private NextReminderListener nextReminderListener;
+
     private View fragmentOverview;
     private MedicineViewModel medicineViewModel;
-    private LatestRemindersViewAdapter adapter;
+    private LatestRemindersViewAdapter latestRemindersViewAdapter;
+    private NextRemindersViewAdapter nextRemindersViewAdapter;
     private LiveData<List<ReminderEvent>> liveData;
     private HandlerThread thread;
     private SwipeHelper swipeHelper;
+    private NextRemindersViewModel nextRemindersViewModel;
+    private List<ReminderEvent> reminderEvents;
+    private List<MedicineWithReminders> medicineWithReminders;
+    private boolean nextRemindersExpanded = false;
 
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
@@ -50,49 +60,44 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
         fragmentOverview = inflater.inflate(R.layout.fragment_overview, container, false);
         medicineViewModel = new ViewModelProvider(this).get(MedicineViewModel.class);
 
-        setupTakenSkippedButtonsAndNextReminderListener();
+        thread = new HandlerThread("LogManualDose");
+        thread.start();
 
-        RecyclerView latestReminders = fragmentOverview.findViewById(R.id.latestReminders);
+        RecyclerView latestReminders = setupLatestReminders();
+        setupNextReminders();
+        setupLogManualDose();
+        setupSwiping(latestReminders);
+        setupExpandNextReminders();
 
-        adapter = new LatestRemindersViewAdapter(new LatestRemindersViewAdapter.ReminderEventDiff());
-        latestReminders.setAdapter(adapter);
+        return fragmentOverview;
+    }
+
+    @NonNull
+    private RecyclerView setupLatestReminders() {
+        RecyclerView latestReminders = fragmentOverview.findViewById(R.id.latestReminders);
+        latestRemindersViewAdapter = new LatestRemindersViewAdapter(new LatestRemindersViewAdapter.ReminderEventDiff());
+        latestReminders.setAdapter(latestRemindersViewAdapter);
         latestReminders.setLayoutManager(new LinearLayoutManager(fragmentOverview.getContext()));
         // Scroll to top as soon as a new item was inserted
-        adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
+        latestRemindersViewAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
             @Override
             public void onItemRangeInserted(int positionStart, int itemCount) {
                 latestReminders.scrollToPosition(0);
             }
         });
-
-        thread = new HandlerThread("LogManualDose");
-        thread.start();
-        setupLogManualDose();
-
-        setupSwiping(latestReminders);
-
-        return fragmentOverview;
+        return latestReminders;
     }
 
-    private void setupTakenSkippedButtonsAndNextReminderListener() {
-        Button takenNow = fragmentOverview.findViewById(R.id.takenNow);
-        Button skippedNow = fragmentOverview.findViewById(R.id.skippedNow);
-        NextReminderListener.NextReminderIsTodayCallback callback = isToday -> {
-            final Handler mainHandler = new Handler(Looper.getMainLooper());
-            mainHandler.post(() -> {
-                takenNow.setVisibility(isToday ? View.VISIBLE : View.GONE);
-                skippedNow.setVisibility(isToday ? View.VISIBLE : View.GONE);
-            });
-        };
+    private void setupNextReminders() {
+        RecyclerView nextReminders = fragmentOverview.findViewById(R.id.nextReminders);
+        nextRemindersViewAdapter = new NextRemindersViewAdapter(new NextRemindersViewAdapter.ScheduledReminderDiff(), medicineViewModel);
+        nextReminders.setAdapter(nextRemindersViewAdapter);
+        nextReminders.setLayoutManager(new LinearLayoutManager(fragmentOverview.getContext()));
 
-        nextReminderListener = new NextReminderListener(fragmentOverview.findViewById(R.id.nextReminderInfo), callback, medicineViewModel);
-        takenNow.setOnClickListener(buttonView -> nextReminderListener.processFutureReminder(true));
-        skippedNow.setOnClickListener(buttonView -> nextReminderListener.processFutureReminder(false));
+        nextRemindersViewModel = new ViewModelProvider(this).get(NextRemindersViewModel.class);
+        nextRemindersViewModel.getScheduledReminders().observe(getViewLifecycleOwner(), this::updatedNextReminders);
 
-        Intent nextReminder = requireContext().registerReceiver(nextReminderListener, new IntentFilter(NEXT_REMINDER_ACTION), Context.RECEIVER_EXPORTED);
-        if (nextReminder != null) {
-            nextReminderListener.onReceive(requireContext(), nextReminder);
-        }
+        setupScheduleObservers();
     }
 
     private void setupLogManualDose() {
@@ -117,7 +122,32 @@ public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, int dire
         };
         ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeHelper);
         itemTouchHelper.attachToRecyclerView(latestReminders);
+    }
 
+    private void setupExpandNextReminders() {
+        MaterialButton expandNextReminders = fragmentOverview.findViewById(R.id.expandNextReminders);
+        MaterialCardView nextRemindersCard = fragmentOverview.findViewById(R.id.nextRemindersCard);
+        expandNextReminders.setOnClickListener(v -> {
+            nextRemindersExpanded = !nextRemindersExpanded;
+            adaptUIToNextRemindersExpandedState(expandNextReminders, nextRemindersCard);
+            updatedNextReminders(nextRemindersViewModel.getScheduledReminders().getValue());
+        });
+
+        adaptUIToNextRemindersExpandedState(expandNextReminders, nextRemindersCard);
+    }
+
+    private void updatedNextReminders(List<ScheduledReminder> scheduledReminders) {
+        if (!nextRemindersExpanded && !scheduledReminders.isEmpty()) {
+            nextRemindersViewAdapter.submitList(scheduledReminders.subList(0, 1));
+        } else {
+            nextRemindersViewAdapter.submitList(scheduledReminders);
+        }
+    }
+
+    private void setupScheduleObservers() {
+        medicineViewModel.getReminderEvents(0, Instant.now().toEpochMilli() / 1000 - 48 * 60 * 60)
+                .observe(getViewLifecycleOwner(), this::changedReminderEvents);
+        medicineViewModel.getMedicines().observe(getViewLifecycleOwner(), this::changedMedicines);
     }
 
     private void navigateToEditEvent(long eventId) {
@@ -135,16 +165,61 @@ private void navigateToEditEvent(long eventId) {
         }
     }
 
+    private void adaptUIToNextRemindersExpandedState(MaterialButton expandNextReminders, MaterialCardView nextRemindersCard) {
+        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) nextRemindersCard.getLayoutParams();
+        if (nextRemindersExpanded) {
+            expandNextReminders.setIconResource(R.drawable.chevron_up);
+            layoutParams.height = 0;
+            layoutParams.weight = 1;
+            nextRemindersCard.setLayoutParams(layoutParams);
+        } else {
+            expandNextReminders.setIconResource(R.drawable.chevron_down);
+            layoutParams.height = WRAP_CONTENT;
+            layoutParams.weight = 0;
+            nextRemindersCard.setLayoutParams(layoutParams);
+        }
+    }
+
+    private void changedReminderEvents(List<ReminderEvent> reminderEvents) {
+        this.reminderEvents = reminderEvents;
+        calculateSchedule();
+    }
+
+    private void changedMedicines(List<MedicineWithReminders> medicineWithReminders) {
+        this.medicineWithReminders = medicineWithReminders;
+        calculateSchedule();
+    }
+
+    private void calculateSchedule() {
+        ReminderScheduler scheduler = new ReminderScheduler(new ReminderScheduler.TimeAccess() {
+            @Override
+            public ZoneId systemZone() {
+                return ZoneId.systemDefault();
+            }
+
+            @Override
+            public LocalDate localDate() {
+                return LocalDate.now();
+            }
+        });
+
+        if (medicineWithReminders != null && reminderEvents != null) {
+            List<ScheduledReminder> reminders = scheduler.schedule(medicineWithReminders, reminderEvents);
+            nextRemindersViewModel.setScheduledReminders(reminders);
+        }
+    }
+
     @Override
     public void onResume() {
         super.onResume();
+
         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(fragmentOverview.getContext());
         long eventAgeHours = Long.parseLong(sharedPref.getString("overview_events", "24"));
         if (liveData != null) {
             liveData.removeObservers(getViewLifecycleOwner());
         }
         liveData = medicineViewModel.getReminderEvents(0, Instant.now().toEpochMilli() / 1000 - (eventAgeHours * 60 * 60));
-        liveData.observe(getViewLifecycleOwner(), adapter::submitList);
+        liveData.observe(getViewLifecycleOwner(), latestRemindersViewAdapter::submitList);
 
         ReminderProcessor.requestReschedule(requireContext());
 
@@ -157,9 +232,5 @@ public void onDestroy() {
         if (thread != null) {
             thread.quitSafely();
         }
-        if (nextReminderListener != null) {
-            requireContext().unregisterReceiver(nextReminderListener);
-            nextReminderListener.stop();
-        }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java
index bafe75e4b..7a53045fa 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java
@@ -6,14 +6,12 @@
 import static com.futsch1.medtimer.ActivityCodes.EXTRA_REMINDER_ID;
 import static com.futsch1.medtimer.ActivityCodes.EXTRA_SNOOZE_TIME;
 import static com.futsch1.medtimer.ActivityCodes.REMINDER_ACTION;
-import static com.futsch1.medtimer.ActivityCodes.RESCHEDULE_ACTION;
 import static com.futsch1.medtimer.ActivityCodes.SNOOZE_ACTION;
 import static com.futsch1.medtimer.ActivityCodes.TAKEN_ACTION;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.work.Data;
@@ -23,16 +21,16 @@
 import androidx.work.WorkManager;
 import androidx.work.WorkRequest;
 
-import com.futsch1.medtimer.LogTags;
 import com.futsch1.medtimer.WorkManagerAccess;
 
 public class ReminderProcessor extends BroadcastReceiver {
 
     public static void requestReschedule(@NonNull Context context) {
-        Log.i(LogTags.SCHEDULER, "Requesting reschedule");
-        Intent intent = new Intent(RESCHEDULE_ACTION);
-        intent.setClass(context, ReminderProcessor.class);
-        context.sendBroadcast(intent);
+        WorkManager workManager = WorkManagerAccess.getWorkManager(context);
+        OneTimeWorkRequest rescheduleWork =
+                new OneTimeWorkRequest.Builder(RescheduleWork.class)
+                        .build();
+        workManager.enqueueUniqueWork("reschedule", ExistingWorkPolicy.KEEP, rescheduleWork);
     }
 
     public static Intent getDismissedActionIntent(@NonNull Context context, int reminderEventId) {
@@ -71,12 +69,7 @@ public static Intent getSnoozeIntent(@NonNull Context context, int reminderId, i
     @Override
     public void onReceive(Context context, Intent intent) {
         WorkManager workManager = WorkManagerAccess.getWorkManager(context);
-        if (RESCHEDULE_ACTION.equals(intent.getAction())) {
-            OneTimeWorkRequest rescheduleWork =
-                    new OneTimeWorkRequest.Builder(RescheduleWork.class)
-                            .build();
-            workManager.enqueueUniqueWork("reschedule", ExistingWorkPolicy.KEEP, rescheduleWork);
-        } else if (DISMISSED_ACTION.equals(intent.getAction())) {
+        if (DISMISSED_ACTION.equals(intent.getAction())) {
             workManager.enqueue(buildActionWorkRequest(intent, DismissWork.class));
         } else if (TAKEN_ACTION.equals(intent.getAction())) {
             workManager.enqueue(buildActionWorkRequest(intent, TakenWork.class));
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/RescheduleWork.java b/app/src/main/java/com/futsch1/medtimer/reminders/RescheduleWork.java
index 09f7fb228..7d42b8f7b 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/RescheduleWork.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/RescheduleWork.java
@@ -20,10 +20,10 @@
 
 import com.futsch1.medtimer.LogTags;
 import com.futsch1.medtimer.PreferencesFragment;
+import com.futsch1.medtimer.ScheduledReminder;
 import com.futsch1.medtimer.WorkManagerAccess;
 import com.futsch1.medtimer.database.MedicineRepository;
 import com.futsch1.medtimer.database.MedicineWithReminders;
-import com.futsch1.medtimer.overview.NextReminderListener;
 import com.futsch1.medtimer.reminders.scheduling.ReminderScheduler;
 
 import java.time.Instant;
@@ -49,7 +49,21 @@ public Result doWork() {
         Log.i(LogTags.REMINDER, "Received scheduler request");
 
         MedicineRepository medicineRepository = new MedicineRepository((Application) getApplicationContext());
-        ReminderScheduler reminderScheduler = new ReminderScheduler((timestamp, medicine, reminder) -> this.schedule(timestamp, reminder.reminderId, medicine.name, -1, 0), new ReminderScheduler.TimeAccess() {
+        ReminderScheduler reminderScheduler = getReminderScheduler();
+        List<MedicineWithReminders> medicineWithReminders = medicineRepository.getMedicines();
+        List<ScheduledReminder> scheduledReminders = reminderScheduler.schedule(medicineWithReminders, medicineRepository.getLastDaysReminderEvents(2));
+        if (!scheduledReminders.isEmpty()) {
+            ScheduledReminder scheduledReminder = scheduledReminders.get(0);
+            this.schedule(scheduledReminder.timestamp(), scheduledReminder.reminder().reminderId, scheduledReminder.medicine().name, -1, 0);
+        }
+
+        return Result.success();
+    }
+
+    @NonNull
+    private ReminderScheduler getReminderScheduler() {
+
+        return new ReminderScheduler(new ReminderScheduler.TimeAccess() {
             @Override
             public ZoneId systemZone() {
                 return ZoneId.systemDefault();
@@ -60,11 +74,6 @@ public LocalDate localDate() {
                 return LocalDate.now();
             }
         });
-
-        List<MedicineWithReminders> medicineWithReminders = medicineRepository.getMedicines();
-        reminderScheduler.schedule(medicineWithReminders, medicineRepository.getLastDaysReminderEvents(2));
-
-        return Result.success();
     }
 
     protected void schedule(Instant timestamp, int reminderId, String medicineName, int requestCode, int reminderEventId) {
@@ -83,8 +92,6 @@ protected void schedule(Instant timestamp, int reminderId, String medicineName,
                 alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timestamp.toEpochMilli(), pendingIntent);
             }
 
-            notifyGUIListener(timestamp, reminderId);
-
             Log.i(LogTags.SCHEDULER, String.format("Scheduled reminder for %s/%d to %s", medicineName, reminderId, timestamp));
         } else {
             // Immediately schedule
@@ -107,9 +114,4 @@ private boolean canScheduleExactAlarms(AlarmManager alarmManager) {
 
         return exactReminders && alarmManager.canScheduleExactAlarms();
     }
-
-    protected void notifyGUIListener(Instant timestamp, int reminderId) {
-        // Notify GUI listener
-        NextReminderListener.sendNextReminder(context, reminderId, timestamp);
-    }
 }
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeWork.java b/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeWork.java
index 760b2c5b6..8b62a57e8 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeWork.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeWork.java
@@ -45,9 +45,4 @@ public Result doWork() {
 
         return Result.success();
     }
-
-    @Override
-    protected void notifyGUIListener(Instant timestamp, int reminderId) {
-        // Intentionally empty
-    }
 }
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderForScheduling.java b/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderForScheduling.java
index 328a7dcf2..f21588e6a 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderForScheduling.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderForScheduling.java
@@ -17,21 +17,42 @@
 public class ReminderForScheduling {
     private final Reminder reminder;
     private final ReminderScheduler.TimeAccess timeAccess;
-    private final List<ReminderEvent> reminderEventList;
+    private final boolean raisedToday;
     private final boolean[] possibleDays;
 
     public ReminderForScheduling(Reminder reminder, List<ReminderEvent> reminderEventList, ReminderScheduler.TimeAccess timeAccess) {
-        this.reminder = reminder;
-        this.reminderEventList = reminderEventList;
         this.timeAccess = timeAccess;
+        this.reminder = reminder;
+        this.raisedToday = isRaisedToday(reminderEventList);
         // Bit map of possible days in the future on where the reminder may be raised
         this.possibleDays = new boolean[31];
     }
 
+    private boolean isRaisedToday(List<ReminderEvent> reminderEventList) {
+        for (ReminderEvent reminderEvent : reminderEventList) {
+            if (isToday(reminderEvent.remindedTimestamp)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isToday(long epochSeconds) {
+        return localDateFromEpochSeconds(epochSeconds).toEpochDay() == today();
+    }
+
+    private LocalDate localDateFromEpochSeconds(long epochSeconds) {
+        return Instant.ofEpochSecond(epochSeconds).atZone(timeAccess.systemZone()).toLocalDate();
+    }
+
+    private long today() {
+        return timeAccess.localDate().toEpochDay();
+    }
+
     public @Nullable Instant getNextScheduledTime() {
         LocalDate nextScheduledDate = getNextScheduledDate();
         if (nextScheduledDate != null) {
-            return nextScheduledDate.atTime(LocalTime.ofSecondOfDay(reminder.timeInMinutes * 60L)).atZone(timeAccess.systemZone()).toInstant();
+            return localDateToReminderInstant(nextScheduledDate);
         } else {
             return null;
         }
@@ -49,9 +70,12 @@ private LocalDate getNextScheduledDate() {
         return getEarliestPossibleDate();
     }
 
-    private void canScheduleEveryDay() {
-        Arrays.fill(possibleDays, true);
-        possibleDays[0] = !createdToday() && notRaisedToday();
+    private Instant localDateToReminderInstant(LocalDate localDate) {
+        return localDate.atTime(LocalTime.ofSecondOfDay(reminder.timeInMinutes * 60L)).atZone(timeAccess.systemZone()).toInstant();
+    }
+
+    private boolean isCyclic() {
+        return reminder.pauseDays != 0;
     }
 
     private void setPossibleDaysByCycle() {
@@ -63,7 +87,12 @@ private void setPossibleDaysByCycle() {
             dayInCycle++;
         }
         // Only schedule today if it's not already raised
-        possibleDays[0] &= notRaisedToday();
+        possibleDays[0] &= !raisedToday;
+    }
+
+    private void canScheduleEveryDay() {
+        Arrays.fill(possibleDays, true);
+        possibleDays[0] = reminderBeforeCreation() && !raisedToday;
     }
 
     private void clearPossibleDaysByWeekday() {
@@ -86,35 +115,7 @@ private LocalDate getEarliestPossibleDate() {
         return null;
     }
 
-    private boolean isCyclic() {
-        return reminder.pauseDays != 0;
-    }
-
-    private long today() {
-        return timeAccess.localDate().toEpochDay();
-    }
-
-    private boolean notRaisedToday() {
-        return neverRaised() || today() != localDateFromEpochSeconds(lastRemindedTimestamp()).toEpochDay();
-    }
-
-    private boolean createdToday() {
-        return isToday(reminder.createdTimestamp);
-    }
-
-    private boolean neverRaised() {
-        return reminderEventList.isEmpty();
-    }
-
-    private LocalDate localDateFromEpochSeconds(long epochSeconds) {
-        return Instant.ofEpochSecond(epochSeconds).atZone(timeAccess.systemZone()).toLocalDate();
-    }
-
-    private long lastRemindedTimestamp() {
-        return reminderEventList.get(reminderEventList.size() - 1).remindedTimestamp;
-    }
-
-    private boolean isToday(long epochSeconds) {
-        return localDateFromEpochSeconds(epochSeconds).toEpochDay() == today();
+    private boolean reminderBeforeCreation() {
+        return reminder.createdTimestamp < localDateToReminderInstant(timeAccess.localDate()).getEpochSecond();
     }
 }
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderScheduler.java b/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderScheduler.java
index 923036c08..a31f35330 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderScheduler.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/scheduling/ReminderScheduler.java
@@ -2,6 +2,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.futsch1.medtimer.ScheduledReminder;
 import com.futsch1.medtimer.database.Medicine;
 import com.futsch1.medtimer.database.MedicineWithReminders;
 import com.futsch1.medtimer.database.Reminder;
@@ -11,36 +12,36 @@
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
 public class ReminderScheduler {
-    private final ScheduleListener listener;
     private final TimeAccess timeAccess;
 
-    public ReminderScheduler(ScheduleListener listener, TimeAccess timeAccess) {
-        this.listener = listener;
+    public ReminderScheduler(TimeAccess timeAccess) {
         this.timeAccess = timeAccess;
     }
 
-    public void schedule(@NonNull List<MedicineWithReminders> medicineWithReminders, List<ReminderEvent> reminderEvents) {
+    public List<ScheduledReminder> schedule(@NonNull List<MedicineWithReminders> medicineWithReminders, @NonNull List<ReminderEvent> reminderEvents) {
         ArrayList<Reminder> reminders = getReminders(medicineWithReminders);
-        Instant nextScheduledTime = null;
-        Reminder nextReminder = null;
+        ArrayList<ScheduledReminder> scheduledReminders = new ArrayList<>();
 
         for (Reminder reminder : reminders) {
             List<ReminderEvent> filteredEvents = getFilteredEvents(reminderEvents, reminder.reminderId);
             ReminderForScheduling reminderForScheduling = new ReminderForScheduling(reminder, filteredEvents, this.timeAccess);
             Instant reminderScheduledTime = reminderForScheduling.getNextScheduledTime();
-            if (nextScheduledTime == null || (reminderScheduledTime != null && reminderScheduledTime.isBefore(nextScheduledTime))) {
-                nextScheduledTime = reminderScheduledTime;
-                nextReminder = reminder;
+
+            if (reminderScheduledTime != null) {
+                scheduledReminders.add(new ScheduledReminder(getMedicine(reminder, medicineWithReminders), reminder, reminderScheduledTime));
             }
         }
 
-        processFoundNextReminder(medicineWithReminders, nextReminder, nextScheduledTime);
+        scheduledReminders.sort(Comparator.comparing(ScheduledReminder::timestamp));
+
+        return scheduledReminders;
     }
 
     private ArrayList<Reminder> getReminders(List<MedicineWithReminders> medicineWithReminders) {
@@ -57,12 +58,6 @@ private List<ReminderEvent> getFilteredEvents(List<ReminderEvent> reminderEvents
         return reminderEvents.stream().filter(event -> event.reminderId == reminderId).collect(Collectors.toList());
     }
 
-    private void processFoundNextReminder(@NonNull List<MedicineWithReminders> medicineWithReminders, Reminder nextReminder, Instant nextScheduledTime) {
-        if (nextReminder != null) {
-            this.listener.schedule(nextScheduledTime, getMedicine(nextReminder, medicineWithReminders), nextReminder);
-        }
-    }
-
     private Medicine getMedicine(Reminder reminder, List<MedicineWithReminders> medicineWithReminders) {
         int medicineId = reminder.medicineRelId;
 
@@ -74,13 +69,10 @@ private Medicine getMedicine(Reminder reminder, List<MedicineWithReminders> medi
         }
     }
 
-    public interface ScheduleListener {
-        void schedule(Instant timestamp, Medicine medicine, Reminder reminder);
-    }
-
     public interface TimeAccess {
         ZoneId systemZone();
 
         LocalDate localDate();
     }
+
 }
diff --git a/app/src/main/java/com/futsch1/medtimer/statistics/MedicinePerDayChart.java b/app/src/main/java/com/futsch1/medtimer/statistics/MedicinePerDayChart.java
index 687c77e3f..dc10b6909 100644
--- a/app/src/main/java/com/futsch1/medtimer/statistics/MedicinePerDayChart.java
+++ b/app/src/main/java/com/futsch1/medtimer/statistics/MedicinePerDayChart.java
@@ -12,6 +12,7 @@
 import com.androidplot.xy.BarFormatter;
 import com.androidplot.xy.BarRenderer;
 import com.androidplot.xy.BoundaryMode;
+import com.androidplot.xy.SimpleXYSeries;
 import com.androidplot.xy.StepMode;
 import com.androidplot.xy.XYGraphWidget;
 import com.androidplot.xy.XYLegendWidget;
@@ -79,14 +80,19 @@ private void setupLegend() {
         XYLegendWidget legend = medicinesPerDayChart.getLegend();
         legend.getTextPaint().setColor(chartHelper.getColor(com.google.android.material.R.attr.colorOnSurface));
         legend.getTextPaint().setTextSize(chartHelper.dpToPx(10.0f));
+        legend.setPadding(chartHelper.dpToPx(4.0f), 0, chartHelper.dpToPx(4.0f), 0);
     }
 
-    public void updateData(List<XYSeries> series) {
+    public void updateData(List<SimpleXYSeries> series) {
         medicinesPerDayChart.clear();
         colorIndex = 0;
+        int numLegendColumns = Math.max(3, (int) Math.ceil(series.size() / 3.0f));
+        int columnSize = (int) medicinesPerDayChart.getLegend().getWidgetDimensions().paddedRect.width() / numLegendColumns;
+        columnSize -= (int) medicinesPerDayChart.getLegend().getIconSize().getWidth().getPixelValue(0.0f) + 2;
 
-        for (XYSeries xySeries : series) {
+        for (SimpleXYSeries xySeries : series) {
             medicinesPerDayChart.addSeries(xySeries, getFormatter(xySeries.getTitle()));
+            adjustTitleLength(xySeries, columnSize, medicinesPerDayChart.getLegend().getTextPaint());
         }
         Number maxRange = calculateMaxRange(series);
         medicinesPerDayChart.setRangeUpperBoundary(maxRange, BoundaryMode.FIXED);
@@ -101,7 +107,7 @@ public void updateData(List<XYSeries> series) {
         medicinesPerDayChart.setDomainStep(StepMode.INCREMENT_BY_VAL, Math.ceil(numDomains / 7.0f));
         medicinesPerDayChart.setDomainBoundaries(minDomain, maxDomain, BoundaryMode.FIXED);
 
-        medicinesPerDayChart.getLegend().setTableModel(new DynamicTableModel(Math.max(3, (int) Math.ceil(series.size() / 3.0f)), 3, TableOrder.ROW_MAJOR));
+        medicinesPerDayChart.getLegend().setTableModel(new DynamicTableModel(numLegendColumns, 3, TableOrder.ROW_MAJOR));
 
         setupRenderer(numDomains);
         medicinesPerDayChart.redraw();
@@ -114,7 +120,17 @@ private MedicinePerDayChartFormatter getFormatter(String title) {
         return formatter;
     }
 
-    private Number calculateMaxRange(List<XYSeries> series) {
+    private void adjustTitleLength(SimpleXYSeries series, int columnPixels, Paint textPaint) {
+        int titleWidth = (int) textPaint.measureText(series.getTitle());
+        String title = series.getTitle();
+        while (titleWidth > columnPixels && title.length() > 5) {
+            title = title.substring(0, title.length() - 4) + "...";
+            titleWidth = (int) textPaint.measureText(title);
+        }
+        series.setTitle(title);
+    }
+
+    private Number calculateMaxRange(List<SimpleXYSeries> series) {
         long max = 0;
         if (series.isEmpty()) {
             return max;
@@ -129,7 +145,7 @@ private Number calculateMaxRange(List<XYSeries> series) {
         return max;
     }
 
-    private long calculateMinDomain(List<XYSeries> series) {
+    private long calculateMinDomain(List<SimpleXYSeries> series) {
         if (series.isEmpty()) {
             return LocalDate.now().toEpochDay() - 1;
         } else {
@@ -137,7 +153,7 @@ private long calculateMinDomain(List<XYSeries> series) {
         }
     }
 
-    private long calculateMaxDomain(List<XYSeries> series) {
+    private long calculateMaxDomain(List<SimpleXYSeries> series) {
         if (series.isEmpty()) {
             return LocalDate.now().toEpochDay();
         } else {
diff --git a/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsFragment.java b/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsFragment.java
index 93a98799f..7524bacd5 100644
--- a/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsFragment.java
+++ b/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsFragment.java
@@ -14,8 +14,8 @@
 import androidx.navigation.Navigation;
 
 import com.androidplot.pie.PieChart;
+import com.androidplot.xy.SimpleXYSeries;
 import com.androidplot.xy.XYPlot;
-import com.androidplot.xy.XYSeries;
 import com.futsch1.medtimer.R;
 import com.futsch1.medtimer.database.MedicineRepository;
 import com.google.android.material.button.MaterialButton;
@@ -103,7 +103,7 @@ private void populateStatistics() {
         statisticsProvider = new StatisticsProvider(medicineRepository);
         int days = analysisDays.getDays();
 
-        List<XYSeries> series = statisticsProvider.getLastDaysReminders(days);
+        List<SimpleXYSeries> series = statisticsProvider.getLastDaysReminders(days);
         requireActivity().runOnUiThread(() -> medicinesPerDayChart.updateData(series));
 
         StatisticsProvider.TakenSkipped data = statisticsProvider.getTakenSkippedData(days);
diff --git a/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsProvider.java b/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsProvider.java
index 73be5078a..dd36ffebd 100644
--- a/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsProvider.java
+++ b/app/src/main/java/com/futsch1/medtimer/statistics/StatisticsProvider.java
@@ -3,7 +3,6 @@
 import androidx.annotation.NonNull;
 
 import com.androidplot.xy.SimpleXYSeries;
-import com.androidplot.xy.XYSeries;
 import com.futsch1.medtimer.database.MedicineRepository;
 import com.futsch1.medtimer.database.ReminderEvent;
 
@@ -39,7 +38,7 @@ private boolean wasAfter(long secondsSinceEpoch, LocalDate date) {
         return instant.atZone(ZoneId.systemDefault()).toLocalDate().isAfter(date);
     }
 
-    public List<XYSeries> getLastDaysReminders(int days) {
+    public List<SimpleXYSeries> getLastDaysReminders(int days) {
         Map<String, int[]> medicineToDayCount = calculateMedicineToDayMap(days);
         return calculateDataEntries(days, medicineToDayCount);
     }
@@ -65,8 +64,8 @@ private Map<String, int[]> calculateMedicineToDayMap(int days) {
      * @noinspection DataFlowIssue
      */
     @NonNull
-    private static List<XYSeries> calculateDataEntries(int days, Map<String, int[]> medicineToDayCount) {
-        List<XYSeries> data = new ArrayList<>();
+    private static List<SimpleXYSeries> calculateDataEntries(int days, Map<String, int[]> medicineToDayCount) {
+        List<SimpleXYSeries> data = new ArrayList<>();
         int seriesCount = medicineToDayCount.size();
         if (seriesCount == 0) {
             return data;
diff --git a/app/src/main/res/drawable/chevron_down.xml b/app/src/main/res/drawable/chevron_down.xml
new file mode 100644
index 000000000..0e55ee5f1
--- /dev/null
+++ b/app/src/main/res/drawable/chevron_down.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16">
+  <path
+      android:pathData="M1.646,4.646a0.5,0.5 0,0 1,0.708 0L8,10.293l5.646,-5.647a0.5,0.5 0,0 1,0.708 0.708l-6,6a0.5,0.5 0,0 1,-0.708 0l-6,-6a0.5,0.5 0,0 1,0 -0.708"
+      android:fillColor="?android:colorForeground"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/app/src/main/res/drawable/chevron_up.xml b/app/src/main/res/drawable/chevron_up.xml
new file mode 100644
index 000000000..3a9fd664a
--- /dev/null
+++ b/app/src/main/res/drawable/chevron_up.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16">
+  <path
+      android:pathData="M7.646,4.646a0.5,0.5 0,0 1,0.708 0l6,6a0.5,0.5 0,0 1,-0.708 0.708L8,5.707l-5.646,5.647a0.5,0.5 0,0 1,-0.708 -0.708z"
+      android:fillColor="?android:colorForeground"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/app/src/main/res/layout/fragment_next_reminder.xml b/app/src/main/res/layout/fragment_next_reminder.xml
new file mode 100644
index 000000000..e3f38ab70
--- /dev/null
+++ b/app/src/main/res/layout/fragment_next_reminder.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_margin="5dp"
+    app:cardCornerRadius="10dp"
+    app:cardElevation="5dp"
+    app:contentPadding="8dp">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/nextReminderText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|center_vertical" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
+
+            <com.google.android.material.chip.ChipGroup
+                android:id="@+id/takenOrSkipped"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:importantForAccessibility="no"
+                app:singleSelection="false">
+
+                <com.google.android.material.chip.Chip
+                    android:id="@+id/takenNow"
+                    style="@style/Widget.MaterialComponents.Chip.Action"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/taken_now"
+                    android:visibility="gone" />
+
+                <com.google.android.material.chip.Chip
+                    android:id="@+id/skippedNow"
+                    style="@style/Widget.MaterialComponents.Chip.Action"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/skip_reminder"
+                    android:visibility="gone" />
+            </com.google.android.material.chip.ChipGroup>
+        </LinearLayout>
+
+    </LinearLayout>
+</com.google.android.material.card.MaterialCardView>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_overview.xml b/app/src/main/res/layout/fragment_overview.xml
index 5a57e35ca..63227ea84 100644
--- a/app/src/main/res/layout/fragment_overview.xml
+++ b/app/src/main/res/layout/fragment_overview.xml
@@ -9,6 +9,7 @@
     tools:context=".overview.OverviewFragment">
 
     <com.google.android.material.card.MaterialCardView
+        android:id="@+id/nextRemindersCard"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_margin="8dp"
@@ -16,48 +17,48 @@
         app:cardElevation="2dp"
         app:contentPadding="10dp">
 
-        <LinearLayout
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/linearLayout"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/next_reminder"
-                android:textStyle="bold" />
+            android:layout_height="match_parent"
+            android:background="?attr/colorSurfaceContainerLow">
 
             <TextView
-                android:id="@+id/nextReminderInfo"
+                android:id="@+id/nextRemindersText"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                app:drawableStartCompat="@drawable/hourglass_split" />
+                android:text="@string/next_reminders"
+                android:textStyle="bold"
+                app:layout_constraintBottom_toTopOf="@+id/nextReminders"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
 
-            <LinearLayout
-                style="?buttonBarStyle"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:orientation="horizontal">
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/nextReminders"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:scrollbars="vertical"
+                app:layout_constraintBottom_toTopOf="@+id/expandNextReminders"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintHeight="wrap_content_constrained"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/nextRemindersText" />
 
-                <Button
-                    android:id="@+id/takenNow"
-                    style="?buttonBarButtonStyle"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:text="@string/taken_now"
-                    android:visibility="gone" />
+            <Button
+                android:id="@+id/expandNextReminders"
+                style="?attr/materialIconButtonFilledTonalStyle"
+                android:layout_width="0dp"
+                android:layout_height="40dp"
+                android:contentDescription="@string/show_all"
+                app:icon="@drawable/chevron_down"
+                app:iconGravity="textStart"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/nextReminders"
+                tools:ignore="TouchTargetSizeCheck" />
 
-                <Button
-                    android:id="@+id/skippedNow"
-                    style="?buttonBarButtonStyle"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:text="@string/skip_reminder"
-                    android:visibility="gone" />
-            </LinearLayout>
-        </LinearLayout>
+        </androidx.constraintlayout.widget.ConstraintLayout>
 
     </com.google.android.material.card.MaterialCardView>
 
@@ -71,6 +72,7 @@
         app:icon="@drawable/capsule" />
 
     <com.google.android.material.card.MaterialCardView
+        android:id="@+id/latestRemindersCard"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_margin="8dp"
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index d58c2832f..77f07c5df 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -24,7 +24,7 @@
     <string name="skipped">Übersprungen</string>
     <string name="reminder_event">%1$s von %2$s, %3$s</string>
     <string name="recent_events">Kürzliche Ereignisse</string>
-    <string name="next_reminder">Nächste Erinnerung</string>
+    <string name="next_reminders">Nächste Erinnerungen</string>
     <plurals name="sum_reminders">
         <item quantity="one">%1$d Erinnerung\n%2$s</item>
         <item quantity="other">%1$d Erinnerungen\n%2$s</item>
@@ -122,4 +122,5 @@
     <string name="taken_now">Jetzt eingenommen</string>
     <string name="event_name">Ereignisname</string>
     <string name="edit_event">Ereignis bearbeiten</string>
+    <string name="show_all">Alle anzeigen</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index db36481dc..8fb0d0fa4 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -27,7 +27,7 @@
     <string name="skipped">Omitido</string>
     <string name="reminder_event">%1$s de %2$s, %3$s</string>
     <string name="recent_events">Eventos recientes</string>
-    <string name="next_reminder">Siguiente recordatorio</string>
+    <string name="next_reminders">Siguientes recordatorios</string>
     <string name="version">Versión %s</string>
     <string name="are_you_sure_delete_reminder">¿Quieres eliminar el recordatorio?</string>
     <string name="clear_events">Restablecer eventos</string>
@@ -121,4 +121,5 @@
     <string name="taken_now">Tomado ahora</string>
     <string name="event_name">Nombre del evento</string>
     <string name="edit_event">Editar evento</string>
+    <string name="show_all">Mostrar todo</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index c7f47b0ea..cd79406dc 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -55,7 +55,7 @@
 
     <string name="recent_events">Événements récents</string>
 
-    <string name="next_reminder">Prochain rappel</string>
+    <string name="next_reminders">Prochains rappels</string>
 
     <string name="version">Version %s</string>
 
@@ -217,5 +217,6 @@
     <string name="taken_now">Pris maintenant</string>
     <string name="event_name">Nom de l\'événement</string>
     <string name="edit_event">Modifier l\'événement</string>
+    <string name="show_all">Afficher tout</string>
 
 </resources>
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index de72548df..fb0cbc6a8 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -28,7 +28,7 @@
     <string name="skipped">Overgeslagen</string>
     <string name="reminder_event">%1$s van %2$s, %3$s</string>
     <string name="recent_events">Recente herinneringen</string>
-    <string name="next_reminder">Volgende herinnering</string>
+    <string name="next_reminders">Volgende herinneringen</string>
     <string name="version">Versie %s</string>
     <string name="are_you_sure_delete_reminder">Weet u zeker dat u de herinnering wilt verwijderen?</string>
     <string name="clear_events">Herinneringen verwijderen</string>
@@ -122,4 +122,5 @@
     <string name="taken_now">Nu ingenomen</string>
     <string name="event_name">"Herinneringennaam   "</string>
     <string name="edit_event">Herinnering bewerken</string>
+    <string name="show_all">Alles weergeven</string>
 </resources>
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index b5d09bf39..17b86a078 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -20,8 +20,6 @@
         <item quantity="one">%1$d hatırlatma\n%2$s</item>
         <item quantity="other">%1$d anımsatıcı\n%2$s</item>
     </plurals>
-    <string name="channel_name" translatable="false">MedTimer</string>
-    <string name="channel_description" translatable="false">Notifications from MedTimer</string>
     <string name="notification_title">İlaç hatırlatıcısı</string>
     <string name="notification_content">Saat %1$s - %3$s%4$s\'den %2$s alma zamanı</string>
     <string name="notification_taken">ALINDI</string>
@@ -29,7 +27,7 @@
     <string name="skipped">Atlandı</string>
     <string name="reminder_event">%1$s / %2$s, %3$s</string>
     <string name="recent_events">Son etkinlikler</string>
-    <string name="next_reminder">Sonraki hatırlatma</string>
+    <string name="next_reminders">Sonraki hatırlatmar</string>
     <string name="version">Sürüm %s</string>
     <string name="are_you_sure_delete_reminder">Hatırlatıcıyı silmek istediğinizden emin misiniz?</string>
     <string name="clear_events">Etkinlikleri temizle</string>
@@ -108,7 +106,6 @@
     <string name="cycle_reminders">Döngüsel hatırlatıcılar</string>
     <string name="weekday_limited">Bazı hafta içi günlerle sınırlıdır</string>
     <string name="reminders">Hatırlatmalar</string>
-    <string name="sort" translatable="false">Sort</string>
     <string name="filter">Filtre</string>
     <string name="seven_days">7 gün</string>
     <string name="analysis">Analiz</string>
@@ -124,4 +121,5 @@
     <string name="taken_now">Şimdi alındı</string>
     <string name="event_name">Etkinlik adı</string>
     <string name="edit_event">Etkinliği düzenle</string>
+    <string name="show_all">Hepsini göster</string>
 </resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5d0559487..3c90977cd 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -29,7 +29,7 @@
     <string name="skipped">Skipped</string>
     <string name="reminder_event">%1$s of %2$s, %3$s</string>
     <string name="recent_events">Recent events</string>
-    <string name="next_reminder">Next reminder</string>
+    <string name="next_reminders">Next reminders</string>
     <string name="version">Version %s</string>
     <string name="are_you_sure_delete_reminder">Are you sure to delete the reminder?</string>
     <string name="clear_events">Clear events</string>
@@ -124,4 +124,5 @@
     <string name="taken_now">Taken now</string>
     <string name="event_name">Event name</string>
     <string name="edit_event">Edit event</string>
+    <string name="show_all">Show all</string>
 </resources>
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 83eea01e4..12121d9c5 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,6 +1,6 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 plugins {
-    id("com.android.application") version "8.4.0" apply false
+    id("com.android.application") version "8.4.1" apply false
     id("androidx.room") version "2.6.1" apply false
     id("androidx.navigation.safeargs") version "2.7.7" apply false
 }


Test patch:
diff --git a/app/src/androidTest/java/com/futsch1/medtimer/BasicUITest.java b/app/src/androidTest/java/com/futsch1/medtimer/BasicUITest.java
index 12d62f99a..74700eb63 100644
--- a/app/src/androidTest/java/com/futsch1/medtimer/BasicUITest.java
+++ b/app/src/androidTest/java/com/futsch1/medtimer/BasicUITest.java
@@ -172,7 +172,7 @@ public void basicUITest() {
         onView(isRoot()).perform(AndroidTestHelper.waitFor(1000));
 
         ViewInteraction textView = onView(
-                allOf(withId(R.id.nextReminderInfo)));
+                new RecyclerViewMatcher(R.id.nextReminders).atPositionOnView(0, R.id.nextReminderText));
         textView.check(matches(withText(startsWith("2 of Test"))));
     }
 
diff --git a/app/src/androidTest/java/com/futsch1/medtimer/StatisticsTest.java b/app/src/androidTest/java/com/futsch1/medtimer/StatisticsTest.java
index 749bdcccb..df9249e3d 100644
--- a/app/src/androidTest/java/com/futsch1/medtimer/StatisticsTest.java
+++ b/app/src/androidTest/java/com/futsch1/medtimer/StatisticsTest.java
@@ -6,6 +6,7 @@
 import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
 import static androidx.test.espresso.action.ViewActions.replaceText;
+import static androidx.test.espresso.action.ViewActions.scrollTo;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
@@ -19,6 +20,7 @@
 import static org.hamcrest.Matchers.startsWith;
 
 import androidx.test.espresso.DataInteraction;
+import androidx.test.espresso.NoMatchingViewException;
 import androidx.test.espresso.ViewInteraction;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -52,14 +54,22 @@ public void statisticsTest() {
                 allOf(withContentDescription("More options")));
         overflowMenuButton.perform(click());
 
-        ViewInteraction materialTextView = onView(
-                allOf(withId(androidx.recyclerview.R.id.title), withText("Generate test data")));
-        materialTextView.perform(click());
-        onView(isRoot()).perform(AndroidTestHelper.waitFor(5000));
-
-        ViewInteraction chip = onView(
-                new RecyclerViewMatcher(R.id.latestReminders).atPositionOnView(0, R.id.chipTaken));
-        chip.perform(click());
+        int retries = 3;
+        while (retries > 0) {
+            ViewInteraction materialTextView = onView(
+                    allOf(withId(androidx.recyclerview.R.id.title), withText("Generate test data")));
+            materialTextView.perform(click());
+            onView(isRoot()).perform(AndroidTestHelper.waitFor(5000));
+
+            ViewInteraction chip = onView(
+                    new RecyclerViewMatcher(R.id.latestReminders).atPositionOnView(0, R.id.chipTaken));
+            try {
+                chip.perform(click());
+                break;
+            } catch (NoMatchingViewException e) {
+                retries--;
+            }
+        }
 
         ViewInteraction chip2 = onView(
                 new RecyclerViewMatcher(R.id.latestReminders).atPositionOnView(1, R.id.chipTaken));
@@ -71,7 +81,7 @@ public void statisticsTest() {
 
         ViewInteraction chip4 = onView(
                 new RecyclerViewMatcher(R.id.latestReminders).atPositionOnView(3, R.id.chipTaken));
-        chip4.perform(click());
+        chip4.perform(scrollTo(), click());
 
         AndroidTestHelper.navigateTo(AndroidTestHelper.MainMenu.ANALYSIS);
 
diff --git a/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerDaysUnitTest.java b/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerDaysUnitTest.java
index 064427499..2e9428b23 100644
--- a/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerDaysUnitTest.java
+++ b/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerDaysUnitTest.java
@@ -1,9 +1,8 @@
 package com.futsch1.medtimer;
 
 import static com.futsch1.medtimer.TestHelper.on;
+import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import com.futsch1.medtimer.database.MedicineWithReminders;
@@ -21,12 +20,11 @@
 public class ReminderSchedulerDaysUnitTest {
     @Test
     public void test_scheduleSkipWeekdays() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(1));
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 1);
@@ -40,19 +38,20 @@ public void test_scheduleSkipWeekdays() {
 
         List<ReminderEvent> reminderEventList = new ArrayList<>();
 
-        scheduler.schedule(medicineList, reminderEventList);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
         // Expect it to be on the 4.1.1970
-        verify(mock, times(1)).schedule(on(4, 480), medicineWithReminders.medicine, reminder);
+        assertEquals(on(4, 480), scheduledReminders.get(0).timestamp());
+        assertEquals(medicineWithReminders.medicine, scheduledReminders.get(0).medicine());
+        assertEquals(reminder, scheduledReminders.get(0).reminder());
     }
 
     @Test
     public void test_scheduleWeekdaysWithDaysBetweenReminders() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 6);
@@ -71,8 +70,10 @@ public void test_scheduleWeekdaysWithDaysBetweenReminders() {
         List<ReminderEvent> reminderEventList = new ArrayList<>();
         //reminderEventList.add(buildReminderEvent(1, on(2, 480).getEpochSecond()));
 
-        scheduler.schedule(medicineList, reminderEventList);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
         // Expect it to be on the 26.1.1970
-        verify(mock, times(1)).schedule(on(19, 480), medicineWithReminders.medicine, reminder);
+        assertEquals(on(19, 480), scheduledReminders.get(0).timestamp());
+        assertEquals(medicineWithReminders.medicine, scheduledReminders.get(0).medicine());
+        assertEquals(reminder, scheduledReminders.get(0).reminder());
     }
 }
diff --git a/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerUnitTest.java b/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerUnitTest.java
index 53b49317b..45ee97233 100644
--- a/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerUnitTest.java
+++ b/app/src/test/java/com/futsch1/medtimer/ReminderSchedulerUnitTest.java
@@ -1,14 +1,12 @@
 package com.futsch1.medtimer;
 
 import static com.futsch1.medtimer.TestHelper.on;
-import static org.mockito.Mockito.clearInvocations;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
+import com.futsch1.medtimer.database.Medicine;
 import com.futsch1.medtimer.database.MedicineWithReminders;
 import com.futsch1.medtimer.database.Reminder;
 import com.futsch1.medtimer.database.ReminderEvent;
@@ -16,6 +14,7 @@
 
 import org.junit.Test;
 
+import java.time.Instant;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.ArrayList;
@@ -25,72 +24,82 @@ public class ReminderSchedulerUnitTest {
 
     @Test
     public void test_scheduleEmptyLists() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         // Two empty lists
-        scheduler.schedule(new ArrayList<>(), new ArrayList<>());
-        verifyNoInteractions(mock);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(new ArrayList<>(), new ArrayList<>());
+        assertTrue(scheduledReminders.isEmpty());
 
         // One medicine without reminders, no reminder events
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
-        scheduler.schedule(new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(new ArrayList<>() {{
             add(medicineWithReminders);
         }}, new ArrayList<>());
-        verifyNoInteractions(mock);
+        assertTrue(scheduledReminders.isEmpty());
 
         // No reminder events
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 12, 1);
+        reminder.createdTimestamp = on(1, 13).getEpochSecond();
         medicineWithReminders.reminders.add(reminder);
-        scheduler.schedule(new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(new ArrayList<>() {{
             add(medicineWithReminders);
         }}, new ArrayList<>());
-        verify(mock, times(1)).schedule(on(2, 12), medicineWithReminders.medicine, reminder);
+        assertEquals(1, scheduledReminders.size());
+        assertReminded(scheduledReminders, on(2, 12), medicineWithReminders.medicine, reminder);
+    }
+
+    private void assertReminded(List<ScheduledReminder> scheduledReminders, Instant timestamp, Medicine medicine, Reminder reminder) {
+        assertRemindedAtIndex(scheduledReminders, timestamp, medicine, reminder, 0);
+    }
+
+    private void assertRemindedAtIndex(List<ScheduledReminder> scheduledReminders, Instant timestamp, Medicine medicine, Reminder reminder, int index) {
+        assertTrue(scheduledReminders.size() > index);
+        assertEquals(timestamp, scheduledReminders.get(index).timestamp());
+        assertEquals(medicine, scheduledReminders.get(index).medicine());
+        assertEquals(reminder, scheduledReminders.get(index).reminder());
     }
 
     @Test
     public void test_scheduleReminders() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders1 = TestHelper.buildMedicineWithReminders(1, "Test1");
         Reminder reminder1 = TestHelper.buildReminder(1, 1, "1", 16, 1);
         Reminder reminder2 = TestHelper.buildReminder(1, 1, "2", 12, 1);
         medicineWithReminders1.reminders.add(reminder1);
         medicineWithReminders1.reminders.add(reminder2);
-        scheduler.schedule(new ArrayList<>() {{
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(new ArrayList<>() {{
             add(medicineWithReminders1);
         }}, new ArrayList<>());
-        verify(mock, times(1)).schedule(on(2, 12), medicineWithReminders1.medicine, reminder2);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(1, 12), medicineWithReminders1.medicine, reminder2);
+        assertRemindedAtIndex(scheduledReminders, on(1, 16), medicineWithReminders1.medicine, reminder1, 1);
 
         // Now add a second medicine with an earlier reminder
         MedicineWithReminders medicineWithReminders2 = TestHelper.buildMedicineWithReminders(2, "Test2");
         Reminder reminder3 = TestHelper.buildReminder(2, 1, "1", 3, 1);
         medicineWithReminders2.reminders.add(reminder3);
-        scheduler.schedule(new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(new ArrayList<>() {{
             add(medicineWithReminders1);
             add(medicineWithReminders2);
         }}, new ArrayList<>());
-        verify(mock, times(1)).schedule(on(2, 3), medicineWithReminders2.medicine, reminder3);
+        assertReminded(scheduledReminders, on(1, 3), medicineWithReminders2.medicine, reminder3);
     }
 
     @Test
     public void test_scheduleWithEvents() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(1));
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders1 = TestHelper.buildMedicineWithReminders(1, "Test1");
         Reminder reminder1 = TestHelper.buildReminder(1, 1, "1", 16, 1);
@@ -105,63 +114,60 @@ public void test_scheduleWithEvents() {
             add(medicineWithReminders2);
         }};
         // Reminder 3 already invoked
-        scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
             add(TestHelper.buildReminderEvent(3, on(2, 3).getEpochSecond()));
         }});
-        verify(mock, times(1)).schedule(on(2, 12), medicineWithReminders1.medicine, reminder2);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(2, 12), medicineWithReminders1.medicine, reminder2);
+        assertRemindedAtIndex(scheduledReminders, on(2, 16), medicineWithReminders1.medicine, reminder1, 1);
+        assertRemindedAtIndex(scheduledReminders, on(3, 3), medicineWithReminders2.medicine, reminder3, 2);
 
         // Check two reminders at the same time
         Reminder reminder4 = TestHelper.buildReminder(2, 4, "1", 12, 1);
         medicineWithReminders2.reminders.add(reminder4);
-        scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
             add(TestHelper.buildReminderEvent(3, on(2, 3).getEpochSecond()));
             add(TestHelper.buildReminderEvent(2, on(2, 12).getEpochSecond()));
         }});
-        verify(mock, times(1)).schedule(on(2, 12), medicineWithReminders2.medicine, reminder4);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(2, 12), medicineWithReminders2.medicine, reminder4);
 
-        scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
             add(TestHelper.buildReminderEvent(3, on(2, 4).getEpochSecond()));
             add(TestHelper.buildReminderEvent(2, on(2, 12).getEpochSecond()));
             add(TestHelper.buildReminderEvent(4, on(2, 12).getEpochSecond()));
         }});
-        verify(mock, times(1)).schedule(on(2, 16), medicineWithReminders1.medicine, reminder1);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(2, 16), medicineWithReminders1.medicine, reminder1);
 
         // All reminders already invoked, switch to next day
-        scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
             add(TestHelper.buildReminderEvent(3, on(2, 4).getEpochSecond() + 4 * 60));
             add(TestHelper.buildReminderEvent(2, on(2, 12).getEpochSecond()));
             add(TestHelper.buildReminderEvent(1, on(2, 16).getEpochSecond()));
             add(TestHelper.buildReminderEvent(4, on(2, 16).getEpochSecond()));
         }});
-        verify(mock, times(1)).schedule(on(3, 3), medicineWithReminders2.medicine, reminder3);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(3, 3), medicineWithReminders2.medicine, reminder3);
 
         // All reminders already invoked, we are on the next day
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(2));
-        scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
+        scheduledReminders = scheduler.schedule(medicineWithReminders, new ArrayList<>() {{
             add(TestHelper.buildReminderEvent(3, on(2, 4).getEpochSecond()));
             add(TestHelper.buildReminderEvent(2, on(2, 12).getEpochSecond()));
             add(TestHelper.buildReminderEvent(1, on(2, 16).getEpochSecond()));
         }});
-        verify(mock, times(1)).schedule(on(3, 3), medicineWithReminders2.medicine, reminder3);
-        clearInvocations(mock);
+        assertReminded(scheduledReminders, on(3, 3), medicineWithReminders2.medicine, reminder3);
     }
 
     // schedules a reminder for the same day
     @Test
     public void test_scheduleSameDayReminder() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 1);
+        reminder.createdTimestamp = on(1, 500).getEpochSecond();
         medicineWithReminders.reminders.add(reminder);
 
         List<MedicineWithReminders> medicineList = new ArrayList<>();
@@ -169,20 +175,19 @@ public void test_scheduleSameDayReminder() {
 
         List<ReminderEvent> reminderEventList = new ArrayList<>();
 
-        scheduler.schedule(medicineList, reminderEventList);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
 
-        verify(mock, times(1)).schedule(on(2, 480), medicineWithReminders.medicine, reminder);
+        assertReminded(scheduledReminders, on(2, 480), medicineWithReminders.medicine, reminder);
     }
 
     // schedules a reminder for a different medicine
     @Test
     public void test_scheduleDifferentMedicineReminder() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(1));
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders1 = TestHelper.buildMedicineWithReminders(1, "Test1");
         Reminder reminder1 = TestHelper.buildReminder(1, 1, "1", 480, 1);
@@ -198,20 +203,19 @@ public void test_scheduleDifferentMedicineReminder() {
 
         List<ReminderEvent> reminderEventList = new ArrayList<>();
 
-        scheduler.schedule(medicineList, reminderEventList);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
 
-        verify(mock, times(1)).schedule(on(2, 480), medicineWithReminders1.medicine, reminder1);
+        assertReminded(scheduledReminders, on(2, 480), medicineWithReminders1.medicine, reminder1);
     }
 
     // schedules a reminder for every two days
     @Test
     public void test_scheduleReminderWithOneDayPause() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 2);
@@ -222,26 +226,24 @@ public void test_scheduleReminderWithOneDayPause() {
 
         List<ReminderEvent> reminderEventList = new ArrayList<>();
 
-        scheduler.schedule(medicineList, reminderEventList);
-
-        verify(mock, times(1)).schedule(on(1, 480), medicineWithReminders.medicine, reminder);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(1, 480), medicineWithReminders.medicine, reminder);
 
         reminderEventList.add(TestHelper.buildReminderEvent(1, on(1, 480).getEpochSecond()));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(1));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(3, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(3, 480), medicineWithReminders.medicine, reminder);
     }
 
     // schedules a reminder for every two days
     @Test
     public void test_scheduleTwoDayReminderVsOneDay() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 2);
@@ -257,18 +259,17 @@ public void test_scheduleTwoDayReminderVsOneDay() {
 
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(1));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(2, 481), medicineWithReminders.medicine, reminder2);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(2, 481), medicineWithReminders.medicine, reminder2);
     }
 
     @Test
     public void test_scheduleReminderWithOneDayPauseVsThreeDaysPause() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 2);
@@ -282,43 +283,41 @@ public void test_scheduleReminderWithOneDayPauseVsThreeDaysPause() {
         List<ReminderEvent> reminderEventList = new ArrayList<>();
         reminderEventList.add(TestHelper.buildReminderEvent(1, on(1, 480).getEpochSecond()));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(1, 481), medicineWithReminders.medicine, reminder2);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(1, 481), medicineWithReminders.medicine, reminder2);
 
         reminderEventList.add(TestHelper.buildReminderEvent(2, on(1, 481).getEpochSecond()));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(3, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(3, 480), medicineWithReminders.medicine, reminder);
 
         // On day 3
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(2));
 
-        reset(mock);
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(3, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(3, 480), medicineWithReminders.medicine, reminder);
 
         reminderEventList.add(TestHelper.buildReminderEvent(1, on(3, 480).getEpochSecond()));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(5, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(5, 480), medicineWithReminders.medicine, reminder);
 
         // On day 5
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(4));
 
         reminderEventList.add(TestHelper.buildReminderEvent(1, on(5, 480).getEpochSecond()));
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(5, 481), medicineWithReminders.medicine, reminder2);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(5, 481), medicineWithReminders.medicine, reminder2);
     }
 
     @Test
     public void test_scheduleCycleInFuture() {
-        ReminderScheduler.ScheduleListener mock = mock(ReminderScheduler.ScheduleListener.class);
         ReminderScheduler.TimeAccess mockTimeAccess = mock(ReminderScheduler.TimeAccess.class);
         when(mockTimeAccess.systemZone()).thenReturn(ZoneId.of("Z"));
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH);
 
-        ReminderScheduler scheduler = new ReminderScheduler(mock, mockTimeAccess);
+        ReminderScheduler scheduler = new ReminderScheduler(mockTimeAccess);
 
         MedicineWithReminders medicineWithReminders = TestHelper.buildMedicineWithReminders(1, "Test");
         Reminder reminder = TestHelper.buildReminder(1, 1, "1", 480, 3);
@@ -330,20 +329,18 @@ public void test_scheduleCycleInFuture() {
 
         List<ReminderEvent> reminderEventList = new ArrayList<>();
 
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(5, 480), medicineWithReminders.medicine, reminder);
+        List<ScheduledReminder> scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(5, 480), medicineWithReminders.medicine, reminder);
 
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(4));
 
-        reset(mock);
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(5, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(5, 480), medicineWithReminders.medicine, reminder);
 
         when(mockTimeAccess.localDate()).thenReturn(LocalDate.EPOCH.plusDays(5));
 
-        reset(mock);
-        scheduler.schedule(medicineList, reminderEventList);
-        verify(mock, times(1)).schedule(on(8, 480), medicineWithReminders.medicine, reminder);
+        scheduledReminders = scheduler.schedule(medicineList, reminderEventList);
+        assertReminded(scheduledReminders, on(8, 480), medicineWithReminders.medicine, reminder);
     }
 
 }
\ No newline at end of file