Fix Strikethrough rendering

Fixes #1444

Markdown strikethrough broken since new update
### Jerboa Version

0.0.62

### Android Version + Phone

Android 13 Samsung a53

### Describe The Bug

Hello :)

Since the last commit (ac39d872a805767d7910531c7619754744b670c8) strike through seems broken with the latest Jeboa app.

Editor screenshot:
![Screenshot_20240311_110011_Jerboa](https://github.com/dessalines/jerboa/assets/95717211/17e0dea7-ec32-4f1c-bb66-3debec9ac9f8)

Post screenshot:
![Screenshot_20240311_105952_Jerboa](https://github.com/dessalines/jerboa/assets/95717211/ce553234-5c12-4319-8267-a2ba90322dfb)

### To Reproduce

1. Create a post
2. Type some text
3. Use the  markdown syntax for strike through`~~text~~`
4. Observe the behavior

### In the case of a crash or when relevant include the logs

_No response_

---

Thanks for everything you do for the fediverse and native lemmy app !  keep it up :muscle: !

diff --git a/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt b/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt
index 9d61dc02d..e931cbcae 100644
--- a/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt
+++ b/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt
@@ -15,7 +15,7 @@ class ScriptRewriteSupportPlugin : AbstractMarkwonPlugin() {

     companion object {
         val SUPERSCRIPT_RGX = Regex("""\^([^\n^]+)\^""")
-        val SUBSCRIPT_RGX = Regex("""~([^\n~]+)~""")
+        val SUBSCRIPT_RGX = Regex("""(?<!~)~([^\n~]+)~""")

         fun rewriteLemmyScriptToMarkwonScript(text: String): String {
             return text

diff --git a/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt b/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt
index 1be365921..0164bacf4 100644
--- a/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt
+++ b/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt
@@ -28,10 +28,16 @@ class ScriptRewriteSupportPluginTest {
             listOf("^2^ ^2^", "2 2"),
             listOf("^^", "^^"),
             listOf("^\n^", "^\n^"),
-            listOf("~2~~2~", "22"),
+            // Due to a parse limitation, the following case isn't fully supported
+            // The negative lookbehind matches with consumed tokens :/
+            listOf("~2~~2~", "2~2~"),
             listOf("~2~\n~2~", "2\n2"),
             listOf("~2~\n~2~", "2\n2"),
             listOf("~ blah blah", "~ blah blah"),
             listOf("", ""),
+            // Strikethrough syntax
+            listOf("~~text~~", "~~text~~"),
+            // Intended to fail, else it will increase the complexity of the regex by a huge margin
+            listOf("~~text~", "~~text~"),
         )
 }


Fix super and sub script not being properly rendered

![image](https://github.com/dessalines/jerboa/assets/67873169/a428351d-fb9b-411f-943c-f8def38badbb)

Fix #1341

Sub and super script in markdown doesn't work
### Jerboa Version

0.0.55

### Android Version + Phone

n/a

### Describe The Bug

The sub and sup markdown actions don't work, it puts the symbols but the markdown renders them as normal.

### To Reproduce

press the sub/sup button, preview the changes

### In the case of a crash or when relevant include the logs

_No response_

Alright not sure why Jerboa uses ~ and ^ for those but markwon never supported that syntax

But they do support script through HTML

![image](https://github.com/dessalines/jerboa/assets/67873169/a88e91e7-645f-42cb-9df0-f2ae53487f71)

So this will be a simple fix

./gradlew :app:testDebugUnitTest --tests "com.jerboa.util.markwon.ScriptRewriteSupportPluginTest"

diff --git a/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt b/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
index dd431924a..fb0f4d1f5 100644
--- a/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
+++ b/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
@@ -32,6 +32,7 @@ import com.jerboa.util.markwon.BetterLinkMovementMethod
 import com.jerboa.util.markwon.ForceHttpsPlugin
 import com.jerboa.util.markwon.MarkwonLemmyLinkPlugin
 import com.jerboa.util.markwon.MarkwonSpoilerPlugin
+import com.jerboa.util.markwon.ScriptRewriteSupportPlugin
 import io.noties.markwon.AbstractMarkwonPlugin
 import io.noties.markwon.Markwon
 import io.noties.markwon.MarkwonConfiguration
@@ -92,6 +93,7 @@ object MarkdownHelper {
                 .usePlugin(ForceHttpsPlugin())
                 // email urls interfere with lemmy links
                 .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
+                .usePlugin(ScriptRewriteSupportPlugin())
                 .usePlugin(MarkwonLemmyLinkPlugin())
                 .usePlugin(MarkwonSpoilerPlugin(true))
                 .usePlugin(StrikethroughPlugin.create())
@@ -127,6 +129,7 @@ object MarkdownHelper {
                 // email urls interfere with lemmy links
                 .usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
                 .usePlugin(MarkwonLemmyLinkPlugin())
+                .usePlugin(ScriptRewriteSupportPlugin())
                 .usePlugin(StrikethroughPlugin.create())
                 .usePlugin(TablePlugin.create(context))
                 .usePlugin(HtmlPlugin.create { plugin -> plugin.addHandler(TagHandlerNoOp.create("img")) })
diff --git a/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt b/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt
new file mode 100644
index 000000000..9d61dc02d
--- /dev/null
+++ b/app/src/main/java/com/jerboa/util/markwon/ScriptRewriteSupportPlugin.kt
@@ -0,0 +1,26 @@
+package com.jerboa.util.markwon
+
+import io.noties.markwon.AbstractMarkwonPlugin
+
+class ScriptRewriteSupportPlugin : AbstractMarkwonPlugin() {
+    override fun processMarkdown(markdown: String): String {
+        return super.processMarkdown(
+            if (markdown.contains("^") || markdown.contains("~")) {
+                rewriteLemmyScriptToMarkwonScript(markdown)
+            } else { // Fast path: if there are no markdown characters, we don't need to do anything
+                markdown
+            },
+        )
+    }
+
+    companion object {
+        val SUPERSCRIPT_RGX = Regex("""\^([^\n^]+)\^""")
+        val SUBSCRIPT_RGX = Regex("""~([^\n~]+)~""")
+
+        fun rewriteLemmyScriptToMarkwonScript(text: String): String {
+            return text
+                .replace(SUPERSCRIPT_RGX, "$1")
+                .replace(SUBSCRIPT_RGX, "$1")
+        }
+    }
+}

diff --git a/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt b/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt
new file mode 100644
index 000000000..1be365921
--- /dev/null
+++ b/app/src/test/java/com/jerboa/util/markwon/ScriptRewriteSupportPluginTest.kt
@@ -0,0 +1,37 @@
+package com.jerboa.util.markwon
+
+import junitparams.JUnitParamsRunner
+import junitparams.Parameters
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(JUnitParamsRunner::class)
+class ScriptRewriteSupportPluginTest {
+    @Test
+    @Parameters(
+        method = "successCases",
+    )
+    fun `should rewrite lemmy script to markwon script`(
+        input: String,
+        expected: String,
+    ) {
+        val result = ScriptRewriteSupportPlugin.rewriteLemmyScriptToMarkwonScript(input)
+        Assert.assertEquals(expected, result)
+    }
+
+    fun successCases() =
+        listOf(
+            listOf("^2^", "2"),
+            listOf("~2~", "2"),
+            listOf("~2~ ~2~", "2 2"),
+            listOf("^2^ ^2^", "2 2"),
+            listOf("^^", "^^"),
+            listOf("^\n^", "^\n^"),
+            listOf("~2~~2~", "22"),
+            listOf("~2~\n~2~", "2\n2"),
+            listOf("~2~\n~2~", "2\n2"),
+            listOf("~ blah blah", "~ blah blah"),
+            listOf("", ""),
+        )
+}


Fix links not working when exclamation mark before it

It didnt work in some cases because it included the space, in the current link matcher.
![image](https://github.com/dessalines/jerboa/assets/67873169/c3485005-f070-4dc4-a7f3-af887e2180fa)

`(?:^|\\s)!($communityPatternFragment)(?:@($instancePatternFragment))?\\b`
This pattern used a non capturing group, but this is still included in the matched string thus it added the space, instead I used a lookbehind since these aren't included in the matched string. Also I updated the tests to include this edge case.

Fixes #795

!community@instance is not clickable if has a exclamation mark before it.
**Jerboa Version**
latest from main

**Describe the bug**
A community@instance is not clickable if it has a exclamation mark before it. Instead it will just collapse the comment.

**To Reproduce**
Try to click on it

go to this post https://lemmy.dbzer0.com/post/81613
try to click on !piracy... link

It does get properly turned into a visible @ but it is not clickable while lemmy-ui doesnt even turn it into a @.

How it looks on lemmy-ui
![image](https://github.com/dessalines/jerboa/assets/67873169/d1e3b30f-5d73-405b-9bd8-6c92e2e1c769)

How it looks on jerboa
![image](https://github.com/dessalines/jerboa/assets/67873169/6020141f-fe75-4727-ae71-0ceb2fecee08)

This post https://lemmy.dbzer0.com/post/81613

Demo

https://github.com/dessalines/jerboa/assets/67873169/1eb15add-9d39-46d7-bf64-2a388d9407aa

Huh weird i have found cases where it does work

this post https://lemmy.world/post/344160
lemmy-ui

![image](https://github.com/dessalines/jerboa/assets/67873169/32bef158-3e35-4832-9abe-4824bfb0d146)

jerboa
![image](https://github.com/dessalines/jerboa/assets/67873169/36271789-eaee-4747-a63f-219610c96241)

![image](https://github.com/dessalines/jerboa/assets/67873169/059c7703-e098-400a-8841-bc8c1f52a326)
Its including the space

```kt
/**
 * Pattern to match lemmy's unique community pattern, e.g. !commmunity[@instance]
 */
val lemmyCommunityPattern: Pattern =
    Pattern.compile("(?:^|\\s)!($communityPatternFragment)(?:@($instancePatternFragment))?\\b")
```

Does this whitespace capture have to be there?

./gradlew :app:testDebugUnitTest --tests "com.jerboa.ui.components.common.LemmyLinkPluginTest"

diff --git a/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt b/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
index ff64aafd0..e61ecb174 100644
--- a/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
+++ b/app/src/main/java/com/jerboa/ui/components/common/MarkdownHelper.kt
@@ -67,13 +67,13 @@ const val userPatternFragment: String = """[a-zA-Z0-9_]{3,}"""
  * Pattern to match lemmy's unique community pattern, e.g. !commmunity[@instance]
  */
 val lemmyCommunityPattern: Pattern =
-    Pattern.compile("(?:^|\\s)!($communityPatternFragment)(?:@($instancePatternFragment))?\\b")
+    Pattern.compile("(?<!\\S)!($communityPatternFragment)(?:@($instancePatternFragment))?\\b")

 /**
  * Pattern to match lemmy's unique user pattern, e.g. @user[@instance]
  */
 val lemmyUserPattern: Pattern =
-    Pattern.compile("(?:^|\\s)@($userPatternFragment)(?:@($instancePatternFragment))?\\b")
+    Pattern.compile("(?<!\\S)@($userPatternFragment)(?:@($instancePatternFragment))?\\b")

 /**
  * Plugin to turn Lemmy-specific URIs into clickable links.

diff --git a/app/src/test/java/com/jerboa/ui/components/common/LemmyLinkPluginTest.kt b/app/src/test/java/com/jerboa/ui/components/common/LemmyLinkPluginTest.kt
index 0875ede7c..09b3e89e5 100644
--- a/app/src/test/java/com/jerboa/ui/components/common/LemmyLinkPluginTest.kt
+++ b/app/src/test/java/com/jerboa/ui/components/common/LemmyLinkPluginTest.kt
@@ -12,10 +12,16 @@ import org.junit.runner.RunWith
 class LemmyLinkPluginTest {
     @Test
     @Parameters(method = "communitySuccessCases")
-    fun testCommunityValid(pattern: String, community: String, instance: String?) {
+    fun testCommunityValid(
+        pattern: String,
+        fullMatch: String,
+        community: String,
+        instance: String?,
+    ) {
         val matcher = lemmyCommunityPattern.matcher(pattern)

         assertTrue(matcher.find())
+        assertEquals(fullMatch, matcher.group(0))
         assertEquals(community, matcher.group(1))
         assertEquals(instance, matcher.group(2))
     }
@@ -34,10 +40,11 @@ class LemmyLinkPluginTest {

     @Test
     @Parameters(method = "userSuccessCases")
-    fun testUserValid(pattern: String, user: String, instance: String?) {
+    fun testUserValid(pattern: String, fullMatch: String, user: String, instance: String?) {
         val matcher = lemmyUserPattern.matcher(pattern)

         assertTrue(matcher.find())
+        assertEquals(fullMatch, matcher.group(0))
         assertEquals(user, matcher.group(1))
         assertEquals(instance, matcher.group(2))
     }
@@ -55,16 +62,18 @@ class LemmyLinkPluginTest {
     }

     fun communitySuccessCases() = listOf(
-        listOf("!community", "community", null),
-        listOf(" !community.", "community", null),
-        listOf("!community@instance.ml", "community", "instance.ml"),
-        listOf("!community@instance.ml!", "community", "instance.ml"),
+        listOf("!community", "!community", "community", null),
+        listOf(" !community.", "!community", "community", null),
+        listOf("!community@instance.ml", "!community@instance.ml", "community", "instance.ml"),
+        listOf(" !community@instance.ml", "!community@instance.ml", "community", "instance.ml"),
+        listOf("!community@instance.ml!", "!community@instance.ml", "community", "instance.ml"),
     )

     fun userSuccessCases() = listOf(
-        listOf("@user", "user", null),
-        listOf(" @user.", "user", null),
-        listOf("@user@instance.ml", "user", "instance.ml"),
-        listOf("@user@instance.ml!", "user", "instance.ml"),
+        listOf("@user", "@user", "user", null),
+        listOf(" @user.", "@user", "user", null),
+        listOf("@user@instance.ml", "@user@instance.ml", "user", "instance.ml"),
+        listOf(" @user@instance.ml", "@user@instance.ml", "user", "instance.ml"),
+        listOf("@user@instance.ml!", "@user@instance.ml", "user", "instance.ml"),
     )
 }


Fix medicine amounts in the thousands being rounded down

**Before:**

https://github.com/user-attachments/assets/71454994-d9a2-4cc7-894c-ab6aeb6f4c22

**After:**

https://github.com/user-attachments/assets/c730402d-abbf-432b-974e-f224741ef5a3

Fixes #797

Medicine amounts in the thousands are rounded down
**Describe the bug**
When entering a decimal medicine amount in the thousands, the value is usually (but not always) rounded down.

**To Reproduce**
1. Go to the medicine pane
2. Enter a name
3. Go to the newly created medicine
4. Go to the medicine stock page
5. Enter 1000 for the amount
6. Exit the page + medicine
7. Observe that the medicine amount is 1000
8. Reenter the medicine and the stock page
9. Enter 1000.5 for the amount
10. Exit the page + medicine
11. Observe that the medicine amount is 1000, not 1000.5

**Expected behavior**
Decimal medicine amounts to be saved properly

**Screenshots**

https://github.com/user-attachments/assets/71454994-d9a2-4cc7-894c-ab6aeb6f4c22

**Smartphone (please complete the following information):**

- Device: Google Pixel 8a
- Android version: Android 15, GrapheneOS build 2025030900

**Additional context**
When you _do_ manage to get a decimal value placed (e.g. by setting the amount to 100, and then 4487.5 afterwards), simply entering and exiting the stock page will result in a high probability of the value being rounded:

https://github.com/user-attachments/assets/ab7dbd00-7574-4fb2-abc2-3cd51e82b7cf

Why is a regex used here?

https://github.com/Futsch1/medTimer/blob/f5ae449597115e0faca19aa8bd452da0b141d2ca/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt#L95-L105
I don't want to require users to put only the number in the amount, but I want to give a bit more flexibility. So the amount string could look like "2 pills" and it would still work, even "depends, but generally 12.5" would work.

./gradlew :app:testDebugUnitTest --tests "com.futsch1.medtimer.MedicineHelperTest"

diff --git a/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt b/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
index 82665be3a..5f0c53ab0 100644
--- a/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
+++ b/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
@@ -93,7 +93,7 @@ object MedicineHelper {
     }

     fun parseAmount(amount: String): Double? {
-        val numberRegex = Pattern.compile("\\d+(?:[.,\\s]\\d+)?")
+        val numberRegex = Pattern.compile("\\d+(?:[.,\\s]\\d+)*")
         val matcher = numberRegex.matcher(amount)

         return if (matcher.find() && matcher.group(0) != null) {

diff --git a/app/src/test/java/com/futsch1/medtimer/MedicineHelperTest.kt b/app/src/test/java/com/futsch1/medtimer/MedicineHelperTest.kt
index b4bfe9317..1f3863f7c 100644
--- a/app/src/test/java/com/futsch1/medtimer/MedicineHelperTest.kt
+++ b/app/src/test/java/com/futsch1/medtimer/MedicineHelperTest.kt
@@ -26,6 +26,8 @@ class MedicineHelperTest {
         assertEquals(50000.0, MedicineHelper.parseAmount("50000"))
         assertEquals(50000.0, MedicineHelper.parseAmount("50,000"))
         assertEquals(50000.0, MedicineHelper.parseAmount("50 000"))
+        assertEquals(1000.5, MedicineHelper.parseAmount("1,000.5"))
+        assertEquals(1000000.42, MedicineHelper.parseAmount("1 000 000.42"))
         assertEquals(3.566, MedicineHelper.parseAmount("3.566 pills"))
         assertEquals(6.23, MedicineHelper.parseAmount("Take 6.23 pills"))
         assertEquals(6.23, MedicineHelper.parseAmount("Take 6.23 pills at 5 o'clock"))


419 bigger button to confirm the medicine taken

Also closes #564 and closes #485

Simplify the content of notifications

Simplify the content of notifications
**Is your feature request related to a problem? Please describe.**
I liked it at first, `It is 12:33 - time to take 1x of Vitamin D` is quite informative, but with multiple notifcations it's a bit unreadable and most of the notification text seems redundant.

**Describe the solution you'd like**
I'd like to keep it simple; either add a new setting or cut out unwanted text. You may prefer the former, as it's possible that not all launchers will display the time label in the notification line.

Just `1x of Vitamin D` with the current notification title looks more appealing to me.
Change police notification color when medicine stock is low
I'd like to know if it could be possible to change police notification color when medicine stock is low?
By doing so, it will make more obvious to the app user that he/she has to worry about the medicine stock each time a notification reminders pop, until a refill above minimal stock level is set.

I don't know if Androïd notification can have a different police colour and if yes, if it can be supported in all Androïd version, so maybe this feature request can't be achieved.

What do you think?

I see your point. I still consider the reminder time important, because you might have several doses of the same medication pending (like the 12:00 dose and the 15:00 dose) and you might want to distinguish those. However, I will consider this input when redesigning the notifications as requested in #419
Sure, but for me it looks like that:

![Image](https://github.com/user-attachments/assets/8aa3e0ab-83cb-48b4-8c8f-507fd3af9ebb)

I already have the notification time, would love it shortened. As I said, even some switch in Settings to make it optional.
Understood. I will definitely change the order of the information, starting with the medication name and the amount.
This would certainly be feasible, but would require a setting to be added since I do not want to make this the default behavior.
Good trip know.
Thank you for the reply and your positive feedback.

If you need some beta tester, please feel free to involve me.

./gradlew :app:testDebugUnitTest --tests "com.futsch1.medtimer.ReminderWorkUnitTest"

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 686a3363a..89718ea5f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -23,8 +23,8 @@ android {
         minSdk = 28
         multiDexEnabled = true
         targetSdk = 36
-        versionCode = 109
-        versionName = "1.16.9"
+        versionCode = 111
+        versionName = "1.16.10"
         base.archivesName = "MedTimer"

         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -207,7 +207,7 @@ android {
     val androidTests = "connectedDebugAndroidTest"
     val exclusions = listOf(
         "**/R.class",
-        "**/R\$*.class",
+        "**/R$*.class",
         "**/BuildConfig.*",
         "**/Manifest*.*",
         "**/*Test*.*",
diff --git a/app/src/main/java/com/futsch1/medtimer/database/Medicine.java b/app/src/main/java/com/futsch1/medtimer/database/Medicine.java
index e74bbe4e7..6c6af5114 100644
--- a/app/src/main/java/com/futsch1/medtimer/database/Medicine.java
+++ b/app/src/main/java/com/futsch1/medtimer/database/Medicine.java
@@ -72,6 +72,10 @@ public Medicine(String name, int id) {
         this.unit = "";
     }

+    public boolean isOutOfStock() {
+        return isStockManagementActive() && amount <= outOfStockReminderThreshold;
+    }
+
     public boolean isStockManagementActive() {
         return (amount != 0 || outOfStockReminder != OutOfStockReminderType.OFF || outOfStockReminderThreshold != 0);
     }
diff --git a/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt b/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
index d1df16aa6..4ee9bba9e 100644
--- a/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
+++ b/app/src/main/java/com/futsch1/medtimer/helpers/MedicineHelper.kt
@@ -3,7 +3,10 @@ package com.futsch1.medtimer.helpers
 import android.annotation.SuppressLint
 import android.content.Context
 import android.text.Editable
+import android.text.SpannableStringBuilder
 import android.text.TextWatcher
+import androidx.core.text.bold
+import androidx.core.text.color
 import androidx.preference.PreferenceManager
 import com.futsch1.medtimer.R
 import com.futsch1.medtimer.database.Medicine
@@ -25,30 +28,50 @@ object MedicineHelper {
         context: Context,
         medicine: Medicine,
         notification: Boolean
-    ): String {
-        val name = getMedicineName(context, medicine, notification)
-        return if (medicine.isStockManagementActive) {
-            "$name (" + context.getString(
-                R.string.medicine_stock_string,
-                formatAmount(medicine.amount, medicine.unit),
-                if (medicine.amount <= medicine.outOfStockReminderThreshold) " ⚠)" else ")"
+    ): SpannableStringBuilder {
+        val builder = SpannableStringBuilder().bold {
+            append(
+                getMedicineName(
+                    context,
+                    medicine,
+                    notification
+                )
             )
-        } else {
-            name
         }
+        if (medicine.isStockManagementActive) {
+            builder.append(" (").append(getStockText(context, medicine))
+                .append(getOutOfStockText(context, medicine)).append(")")
+        }
+        return builder
     }

     @JvmStatic
-    fun getMedicineNameWithStockText(context: Context, medicine: Medicine): String {
-        return getMedicineNameWithStockTextInternal(context, medicine, false)
+    fun getStockText(context: Context, medicine: Medicine): String {
+        return context.getString(
+            R.string.medicine_stock_string,
+            formatAmount(medicine.amount, medicine.unit)
+        )
     }

     @JvmStatic
-    fun getMedicineNameWithStockTextForNotification(context: Context, medicine: Medicine): String {
-        return getMedicineNameWithStockTextInternal(context, medicine, true)
+    fun getOutOfStockText(
+        context: Context,
+        medicine: Medicine
+    ): SpannableStringBuilder {
+        if (medicine.isOutOfStock) {
+            return SpannableStringBuilder().append(" ")
+                .color(context.getColor(android.R.color.holo_red_dark)) { append("⚠") }
+        }
+        return SpannableStringBuilder()
     }

-    private fun getMedicineName(
+    @JvmStatic
+    fun getMedicineNameWithStockText(context: Context, medicine: Medicine): SpannableStringBuilder {
+        return getMedicineNameWithStockTextInternal(context, medicine, false)
+    }
+
+    @JvmStatic
+    fun getMedicineName(
         context: Context,
         medicine: Medicine,
         notification: Boolean
diff --git a/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java
index a81d51c39..a5440df9a 100644
--- a/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java
+++ b/app/src/main/java/com/futsch1/medtimer/overview/NextRemindersViewHolder.java
@@ -73,7 +73,7 @@ private void processFutureReminder(ScheduledReminder scheduledReminder, boolean
                 long reminderEventId = medicineViewModel.medicineRepository.insertReminderEvent(reminderEvent);
                 itemView.getContext().sendBroadcast(taken ?
                                 ReminderProcessor.getTakenActionIntent(itemView.getContext(), (int) reminderEventId)
-                                : ReminderProcessor.getDismissedActionIntent(itemView.getContext(), (int) reminderEventId),
+                                : ReminderProcessor.getSkippedActionIntent(itemView.getContext(), (int) reminderEventId),
                         "com.futsch1.medtimer.NOTIFICATION_PROCESSED");
             }
         });
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/Notifications.java b/app/src/main/java/com/futsch1/medtimer/reminders/Notifications.java
index b23d51a2a..5532d2bed 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/Notifications.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/Notifications.java
@@ -3,31 +3,20 @@
 import android.annotation.SuppressLint;
 import android.app.Notification;
 import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
-import android.graphics.Color;
-import android.os.Build;
 import android.util.Log;

 import androidx.annotation.NonNull;
-import androidx.core.app.NotificationCompat;
-import androidx.preference.PreferenceManager;

 import com.futsch1.medtimer.LogTags;
-import com.futsch1.medtimer.MainActivity;
-import com.futsch1.medtimer.R;
-import com.futsch1.medtimer.ReminderNotificationChannelManager;
 import com.futsch1.medtimer.database.FullMedicine;
 import com.futsch1.medtimer.database.Medicine;
 import com.futsch1.medtimer.database.Reminder;
 import com.futsch1.medtimer.database.ReminderEvent;
-import com.futsch1.medtimer.helpers.MedicineHelper;
-import com.futsch1.medtimer.helpers.MedicineIcons;
-
-import java.util.List;
-import java.util.stream.Collectors;
+import com.futsch1.medtimer.reminders.notificationFactory.OutOfStockNotificationFactory;
+import com.futsch1.medtimer.reminders.notificationFactory.ReminderNotificationFactory;
+import com.futsch1.medtimer.reminders.notificationFactory.ReminderNotificationFactoryKt;

 @SuppressLint("DefaultLocale")
 public class Notifications {
@@ -43,32 +32,10 @@ public Notifications(@NonNull Context context) {
     @SuppressWarnings("java:S107")
     public int showNotification(String remindTime, FullMedicine medicine, Reminder reminder, ReminderEvent reminderEvent) {
         int notificationId = getNextNotificationId();
-        ReminderNotificationChannelManager.Importance importance = (medicine.medicine.notificationImportance == ReminderNotificationChannelManager.Importance.HIGH.getValue()) ? ReminderNotificationChannelManager.Importance.HIGH : ReminderNotificationChannelManager.Importance.DEFAULT;
-        Color color = medicine.medicine.useColor ? Color.valueOf(medicine.medicine.color) : null;
-
-        PendingIntent contentIntent = getStartAppIntent(notificationId);
-
-        String notificationChannelId = ReminderNotificationChannelManager.Companion.getNotificationChannel(context, importance).getId();
-        String notificationMessage = getNotificationString(remindTime, reminder, medicine);
-        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, notificationChannelId)
-                .setSmallIcon(R.drawable.capsule)
-                .setContentTitle(context.getString(R.string.notification_title))
-                .setStyle(new NotificationCompat.BigTextStyle().bigText(notificationMessage))
-                .setContentText(notificationMessage)
-                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
-                .setCategory(Notification.CATEGORY_REMINDER)
-                .setContentIntent(contentIntent);
-        if (medicine.medicine.iconId != 0) {
-            MedicineIcons icons = new MedicineIcons(context);
-            builder.setLargeIcon(icons.getIconBitmap(medicine.medicine.iconId));
-        }
-        if (color != null) {
-            builder = builder.setColor(color.toArgb()).setColorized(true);
-        }
-
-        buildActions(builder, notificationId, reminderEvent.reminderEventId, reminder);
-
-        notify(notificationId, builder.build());
+
+        ReminderNotificationFactory factory = ReminderNotificationFactoryKt.getReminderNotificationFactory(context, notificationId, remindTime, medicine, reminder, reminderEvent);
+
+        notify(notificationId, factory.create());
         Log.d(LogTags.REMINDER, String.format("Created notification %d", notificationId));

         return notificationId;
@@ -82,68 +49,9 @@ private int getNextNotificationId() {
         return notificationId;
     }

-    private PendingIntent getStartAppIntent(int notificationId) {
-        Intent startApp = new Intent(context, MainActivity.class);
-        startApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        return PendingIntent.getActivity(context, notificationId, startApp, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
-    }
-
-    private String getNotificationString(String remindTime, Reminder reminder, FullMedicine medicine) {
-        String instructions = reminder.instructions;
-        if (instructions == null) {
-            instructions = "";
-        }
-        if (!instructions.isEmpty()) {
-            instructions = " " + instructions;
-        }
-        final int amountStringId = reminder.amount.isBlank() ? R.string.notification_content_blank : R.string.notification_content;
-        String medicineNameString = MedicineHelper.getMedicineNameWithStockTextForNotification(context, medicine.medicine);
-        String notificationString = context.getString(amountStringId, remindTime, reminder.amount, medicineNameString, instructions);
-        @SuppressWarnings("java:S6204")
-        List<String> tagNames = medicine.tags.stream().map(t -> t.name).collect(Collectors.toList());
-        if (tagNames.isEmpty()) {
-            return notificationString;
-        }
-        return notificationString + "\n(" + String.join(", ", tagNames) + ")";
-    }
-
-    private void buildActions(NotificationCompat.Builder builder, int notificationId, int reminderEventId, Reminder reminder) {
-        SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-        String dismissNotificationAction = defaultSharedPreferences.getString("dismiss_notification_action", "0");
-        int snoozeTime = Integer.parseInt(defaultSharedPreferences.getString("snooze_duration", "15"));
-        boolean stickyOnLockscreen = defaultSharedPreferences.getBoolean("sticky_on_lockscreen", false);
-
-        PendingIntent pendingSnooze = getSnoozePendingIntent(context, reminder.reminderId, reminderEventId, notificationId, snoozeTime);
-
-        Intent notifyDismissed = ReminderProcessor.getDismissedActionIntent(context, reminderEventId);
-        PendingIntent pendingDismissed = PendingIntent.getBroadcast(context, notificationId, notifyDismissed, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
-
-        PendingIntent pendingTaken = getTakenPendingIntent(notificationId, reminderEventId, reminder);
-
-        if (dismissNotificationAction.equals("0")) {
-            builder.addAction(R.drawable.check2_circle, context.getString(R.string.taken), pendingTaken);
-            builder.addAction(R.drawable.hourglass_split, context.getString(R.string.snooze), pendingSnooze);
-            builder.setDeleteIntent(pendingDismissed);
-        } else if (dismissNotificationAction.equals("1")) {
-            builder.addAction(R.drawable.check2_circle, context.getString(R.string.taken), pendingTaken);
-            builder.addAction(R.drawable.x_circle, context.getString(R.string.skipped), pendingDismissed);
-            builder.setDeleteIntent(pendingSnooze);
-        } else {
-            builder.addAction(R.drawable.x_circle, context.getString(R.string.skipped), pendingDismissed);
-            builder.addAction(R.drawable.hourglass_split, context.getString(R.string.snooze), pendingSnooze);
-            builder.setDeleteIntent(pendingTaken);
-        }
-
-
-        // Later than Android 14, make notification ongoing so that it cannot be dismissed from the lock screen
-        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && stickyOnLockscreen) {
-            builder.setOngoing(true);
-        }
-    }

     private void notify(int notificationId, Notification notification) {
         NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
-
         NotificationSoundManager soundManager = new NotificationSoundManager(context);

         notificationManager.notify(notificationId, notification);
@@ -151,50 +59,13 @@ private void notify(int notificationId, Notification notification) {
         soundManager.restore();
     }

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

     public void showOutOfStockNotification(Medicine medicine) {
         int notificationId = getNextNotificationId();
-        ReminderNotificationChannelManager.Importance importance = (medicine.notificationImportance == ReminderNotificationChannelManager.Importance.HIGH.getValue()) ? ReminderNotificationChannelManager.Importance.HIGH : ReminderNotificationChannelManager.Importance.DEFAULT;
-        Color color = medicine.useColor ? Color.valueOf(medicine.color) : null;
-        NotificationManager notificationManager = context.getSystemService(NotificationManager.class);

-        PendingIntent contentIntent = getStartAppIntent(notificationId);
-
-        String notificationChannelId = ReminderNotificationChannelManager.Companion.getNotificationChannel(context, importance).getId();
-        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, notificationChannelId)
-                .setSmallIcon(R.drawable.box_seam)
-                .setContentTitle(context.getString(R.string.out_of_stock_notification_title))
-                .setContentText(context.getString(R.string.out_of_stock_notification, medicine.name, MedicineHelper.formatAmount(medicine.amount, medicine.unit)))
-                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
-                .setContentIntent(contentIntent);
-        if (medicine.iconId != 0) {
-            MedicineIcons icons = new MedicineIcons(context);
-            builder.setLargeIcon(icons.getIconBitmap(medicine.iconId));
-        }
-        if (color != null) {
-            builder = builder.setColor(color.toArgb()).setColorized(true);
-        }
-
-        notificationManager.notify(notificationId, builder.build());
+        OutOfStockNotificationFactory factory = new OutOfStockNotificationFactory(context, notificationId, medicine);
+
+        notify(notificationId, factory.create());
         Log.d(LogTags.REMINDER, String.format("Created notification %d", notificationId));
     }
 }
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 2f59d1efe..3fdaeb267 100644
--- a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessor.java
@@ -90,7 +90,7 @@ public static void requestStockHandling(Context context, String amount, int medi
     }

     public static void requestActionIntent(Context context, int reminderEventId, boolean taken) {
-        Intent actionIntent = taken ? getTakenActionIntent(context, reminderEventId) : getDismissedActionIntent(context, reminderEventId);
+        Intent actionIntent = taken ? getTakenActionIntent(context, reminderEventId) : getSkippedActionIntent(context, reminderEventId);
         if (taken) {
             WorkManagerAccess.getWorkManager(context).enqueue(buildActionWorkRequest(actionIntent, TakenWork.class));
         } else {
@@ -102,7 +102,7 @@ public static Intent getTakenActionIntent(@NonNull Context context, int reminder
         return buildActionIntent(context, reminderEventId, TAKEN_ACTION);
     }

-    public static Intent getDismissedActionIntent(@NonNull Context context, int reminderEventId) {
+    public static Intent getSkippedActionIntent(@NonNull Context context, int reminderEventId) {
         return buildActionIntent(context, reminderEventId, DISMISSED_ACTION);
     }

diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/BigReminderNotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/BigReminderNotificationFactory.kt
new file mode 100644
index 000000000..40b233c3e
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/BigReminderNotificationFactory.kt
@@ -0,0 +1,54 @@
+package com.futsch1.medtimer.reminders.notificationFactory
+
+import android.content.Context
+import android.widget.RemoteViews
+import com.futsch1.medtimer.R
+import com.futsch1.medtimer.database.FullMedicine
+import com.futsch1.medtimer.database.Reminder
+import com.futsch1.medtimer.database.ReminderEvent
+
+class BigReminderNotificationFactory(
+    context: Context,
+    notificationId: Int,
+    remindTime: String,
+    medicine: FullMedicine,
+    reminder: Reminder,
+    reminderEvent: ReminderEvent
+) : ReminderNotificationFactory(
+    context,
+    notificationId,
+    remindTime,
+    medicine,
+    reminder,
+    reminderEvent
+) {
+    val views: RemoteViews = RemoteViews(context.packageName, R.layout.notification)
+
+    override fun build() {
+        views.setTextViewText(
+            R.id.notificationTitle,
+            getNotificationString()
+        )
+
+        views.setOnClickPendingIntent(R.id.takenButton, pendingTaken)
+        views.setOnClickPendingIntent(R.id.skippedButton, pendingSkipped)
+        views.setOnClickPendingIntent(R.id.snoozeButton, pendingSnooze)
+        views.setTextViewCompoundDrawablesRelative(
+            R.id.notificationTitle,
+            if (medicine.medicine.isOutOfStock) R.drawable.exclamation_triangle_fill else 0,
+            0,
+            0,
+            0
+        )
+
+        builder.setCustomBigContentView(views)
+        builder.setContentText(baseString)
+
+        buildActions()
+    }
+
+    override fun showOutOfStockIcon(): Boolean {
+        return false
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/NotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/NotificationFactory.kt
new file mode 100644
index 000000000..ab193da4a
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/NotificationFactory.kt
@@ -0,0 +1,52 @@
+package com.futsch1.medtimer.reminders.notificationFactory
+
+import android.app.Notification
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import androidx.core.app.NotificationCompat
+import com.futsch1.medtimer.MainActivity
+import com.futsch1.medtimer.ReminderNotificationChannelManager.Companion.getNotificationChannel
+import com.futsch1.medtimer.ReminderNotificationChannelManager.Importance
+import com.futsch1.medtimer.database.Medicine
+import com.futsch1.medtimer.helpers.MedicineIcons
+
+
+abstract class NotificationFactory(
+    val context: Context,
+    val notificationId: Int,
+    medicine: Medicine
+) {
+    val builder: NotificationCompat.Builder
+
+    init {
+        val importance =
+            if (medicine.notificationImportance == Importance.HIGH.value) Importance.HIGH else Importance.DEFAULT
+        val notificationChannelId = getNotificationChannel(context, importance).id
+        builder = NotificationCompat.Builder(context, notificationChannelId)
+
+        val color = if (medicine.useColor) Color.valueOf(medicine.color) else null
+        if (medicine.iconId != 0) {
+            val icons = MedicineIcons(context)
+            builder.setLargeIcon(icons.getIconBitmap(medicine.iconId))
+        }
+        if (color != null) {
+            builder.setColor(color.toArgb()).setColorized(true)
+        }
+
+    }
+
+    fun getStartAppIntent(): PendingIntent? {
+        val startApp = Intent(context, MainActivity::class.java)
+        startApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+        return PendingIntent.getActivity(
+            context,
+            notificationId,
+            startApp,
+            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+        )
+    }
+
+    abstract fun create(): Notification
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/OutOfStockNotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/OutOfStockNotificationFactory.kt
new file mode 100644
index 000000000..bbdb6d996
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/OutOfStockNotificationFactory.kt
@@ -0,0 +1,32 @@
+package com.futsch1.medtimer.reminders.notificationFactory
+
+import android.app.Notification
+import android.content.Context
+import androidx.core.app.NotificationCompat
+import com.futsch1.medtimer.R
+import com.futsch1.medtimer.database.Medicine
+import com.futsch1.medtimer.helpers.MedicineHelper.formatAmount
+
+class OutOfStockNotificationFactory(context: Context, notificationId: Int, medicine: Medicine) :
+    NotificationFactory(context, notificationId, medicine) {
+
+    init {
+        val contentIntent = getStartAppIntent()
+
+        builder.setSmallIcon(R.drawable.box_seam)
+            .setContentTitle(context.getString(R.string.out_of_stock_notification_title))
+            .setContentText(
+                context.getString(
+                    R.string.out_of_stock_notification,
+                    medicine.name,
+                    formatAmount(medicine.amount, medicine.unit)
+                )
+            )
+            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+            .setContentIntent(contentIntent)
+    }
+
+    override fun create(): Notification {
+        return builder.build()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/ReminderNotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/ReminderNotificationFactory.kt
new file mode 100644
index 000000000..b8d0154db
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/ReminderNotificationFactory.kt
@@ -0,0 +1,276 @@
+package com.futsch1.medtimer.reminders.notificationFactory
+
+import android.app.Notification
+import android.app.PendingIntent
+import android.content.Context
+import android.content.SharedPreferences
+import android.os.Build
+import android.text.SpannableStringBuilder
+import androidx.core.app.NotificationCompat
+import androidx.core.text.bold
+import androidx.preference.PreferenceManager
+import com.futsch1.medtimer.R
+import com.futsch1.medtimer.database.FullMedicine
+import com.futsch1.medtimer.database.Reminder
+import com.futsch1.medtimer.database.ReminderEvent
+import com.futsch1.medtimer.database.Tag
+import com.futsch1.medtimer.helpers.MedicineHelper
+import com.futsch1.medtimer.reminders.ReminderProcessor
+import java.util.stream.Collectors
+
+
+fun getReminderNotificationFactory(
+    context: Context,
+    notificationId: Int,
+    remindTime: String,
+    medicine: FullMedicine,
+    reminder: Reminder,
+    reminderEvent: ReminderEvent
+): ReminderNotificationFactory {
+    val defaultPreferences: SharedPreferences =
+        PreferenceManager.getDefaultSharedPreferences(context)
+    return if (defaultPreferences.getBoolean("big_notifications", false)) {
+        BigReminderNotificationFactory(
+            context,
+            notificationId,
+            remindTime,
+            medicine,
+            reminder,
+            reminderEvent
+        )
+    } else {
+        SimpleReminderNotificationFactory(
+            context,
+            notificationId,
+            remindTime,
+            medicine,
+            reminder,
+            reminderEvent
+        )
+    }
+}
+
+abstract class ReminderNotificationFactory(
+    context: Context,
+    notificationId: Int,
+    val remindTime: String,
+    val medicine: FullMedicine,
+    val reminder: Reminder,
+    val reminderEvent: ReminderEvent
+) : NotificationFactory(context, notificationId, medicine.medicine) {
+    val defaultSharedPreferences: SharedPreferences =
+        PreferenceManager.getDefaultSharedPreferences(context)
+    val baseString: SpannableStringBuilder
+
+    val pendingSnooze = getSnoozePendingIntent()
+    val pendingSkipped = getSkippedPendingIntent()
+    val pendingTaken = getTakenPendingIntent()
+
+    val dismissNotificationAction: String? =
+        defaultSharedPreferences.getString("dismiss_notification_action", "0")
+
+    init {
+        val contentIntent: PendingIntent? = getStartAppIntent()
+
+        builder.setSmallIcon(R.drawable.capsule)
+            .setContentTitle(context.getString(R.string.notification_title))
+            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+            .setCategory(Notification.CATEGORY_REMINDER)
+            .setContentIntent(contentIntent)
+
+        val medicineNameString =
+            MedicineHelper.getMedicineName(context, medicine.medicine, true)
+        baseString = SpannableStringBuilder().bold { append(medicineNameString) }
+            .append(" (${reminder.amount})")
+
+        addDismissNotification()
+
+        // Later than Android 14, make notification ongoing so that it cannot be dismissed from the lock screen
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && defaultSharedPreferences.getBoolean(
+                "sticky_on_lockscreen",
+                false
+            )
+        ) {
+            builder.setOngoing(true)
+        }
+    }
+
+    private fun addDismissNotification() {
+        if (dismissNotificationAction == "0") {
+            builder.setDeleteIntent(pendingSkipped)
+        } else if (dismissNotificationAction == "1") {
+            builder.setDeleteIntent(pendingSnooze)
+        } else {
+            builder.setDeleteIntent(pendingTaken)
+        }
+
+    }
+
+    abstract fun build()
+
+    override fun create(): Notification {
+        build()
+        return builder.build()
+    }
+
+    fun getTakenPendingIntent(
+    ): PendingIntent? {
+        return if (reminder.variableAmount) {
+            val notifyTaken = ReminderProcessor.getVariableAmountActionIntent(
+                context,
+                reminderEvent.reminderEventId,
+                reminder.amount
+            )
+            PendingIntent.getActivity(
+                context,
+                notificationId,
+                notifyTaken,
+                PendingIntent.FLAG_IMMUTABLE
+            )
+        } else {
+            val notifyTaken =
+                ReminderProcessor.getTakenActionIntent(context, reminderEvent.reminderEventId)
+            PendingIntent.getBroadcast(
+                context,
+                notificationId,
+                notifyTaken,
+                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+            )
+        }
+    }
+
+    fun getInstructions(): String {
+        var instructions = reminder.instructions
+        if (instructions == null) {
+            instructions = ""
+        }
+        return addLineBreakIfNotEmpty(instructions)
+    }
+
+    fun addLineBreakIfNotEmpty(string: String): String {
+        return if (string.isEmpty()) {
+            string
+        } else {
+            "$string\n"
+        }
+    }
+
+    fun getNotificationString(): SpannableStringBuilder {
+        var builder = SpannableStringBuilder(baseString).append("\n${getInstructions()}")
+        if (medicine.medicine.isStockManagementActive) {
+            builder.append(MedicineHelper.getStockText(context, medicine.medicine))
+            if (showOutOfStockIcon()) {
+                builder.append(MedicineHelper.getOutOfStockText(context, medicine.medicine))
+            }
+            builder.append("\n")
+        }
+
+        builder.append("$remindTime\n${getTagNames()}")
+        return builder
+    }
+
+    open fun showOutOfStockIcon(): Boolean {
+        return true
+    }
+
+    fun getTagNames(): String {
+        val tagNames = medicine.tags.stream().map<String?> { t: Tag? -> t!!.name }
+            .collect(Collectors.toList())
+        return java.lang.String.join(", ", tagNames)
+    }
+
+    fun getSkippedPendingIntent(): PendingIntent {
+        val notifySkipped =
+            ReminderProcessor.getSkippedActionIntent(context, reminderEvent.reminderEventId)
+        return PendingIntent.getBroadcast(
+            context,
+            notificationId,
+            notifySkipped,
+            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+        )
+    }
+
+    fun getSnoozePendingIntent(): PendingIntent {
+        val snoozeTime = defaultSharedPreferences.getString("snooze_duration", "15")!!.toInt()
+
+        fun getSnoozeCustomTimeIntent(): PendingIntent {
+            val snooze = ReminderProcessor.getCustomSnoozeActionIntent(
+                context,
+                reminder.reminderId,
+                reminderEvent.reminderEventId,
+                notificationId
+            )
+            return PendingIntent.getActivity(
+                context,
+                notificationId,
+                snooze,
+                PendingIntent.FLAG_IMMUTABLE
+            )
+        }
+
+        fun getStandardSnoozeIntent(): PendingIntent {
+            val snooze = ReminderProcessor.getSnoozeIntent(
+                context,
+                reminder.reminderId,
+                reminderEvent.reminderEventId,
+                notificationId,
+                snoozeTime
+            )
+            return PendingIntent.getBroadcast(
+                context,
+                notificationId,
+                snooze,
+                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+            )
+        }
+
+        return if (snoozeTime == -1) {
+            getSnoozeCustomTimeIntent()
+        } else {
+            getStandardSnoozeIntent()
+        }
+    }
+
+
+    fun buildActions(
+    ) {
+        val dismissNotificationAction: String? =
+            defaultSharedPreferences.getString("dismiss_notification_action", "0")
+
+        if (dismissNotificationAction == "0") {
+            addTakenAction()
+            addSnoozeAction()
+        } else if (dismissNotificationAction == "1") {
+            addTakenAction()
+            addSkippedAction()
+        } else {
+            addSkippedAction()
+            addSnoozeAction()
+        }
+    }
+
+    private fun addSkippedAction() {
+        builder.addAction(
+            R.drawable.x_circle,
+            context.getString(R.string.skipped),
+            pendingSkipped
+        )
+    }
+
+    private fun addSnoozeAction() {
+        builder.addAction(
+            R.drawable.hourglass_split,
+            context.getString(R.string.snooze),
+            pendingSnooze
+        )
+    }
+
+    private fun addTakenAction() {
+        builder.addAction(
+            R.drawable.check2_circle,
+            context.getString(R.string.taken),
+            pendingTaken
+        )
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/SimpleReminderNotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/SimpleReminderNotificationFactory.kt
new file mode 100644
index 000000000..75877f9d9
--- /dev/null
+++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationFactory/SimpleReminderNotificationFactory.kt
@@ -0,0 +1,32 @@
+package com.futsch1.medtimer.reminders.notificationFactory
+
+import android.content.Context
+import androidx.core.app.NotificationCompat
+import com.futsch1.medtimer.database.FullMedicine
+import com.futsch1.medtimer.database.Reminder
+import com.futsch1.medtimer.database.ReminderEvent
+
+class SimpleReminderNotificationFactory(
+    context: Context,
+    notificationId: Int,
+    remindTime: String,
+    medicine: FullMedicine,
+    reminder: Reminder,
+    reminderEvent: ReminderEvent
+) : ReminderNotificationFactory(
+    context,
+    notificationId,
+    remindTime,
+    medicine,
+    reminder,
+    reminderEvent
+) {
+    override fun build() {
+        val notificationMessage = getNotificationString()
+
+        builder.setStyle(NotificationCompat.BigTextStyle().bigText(notificationMessage))
+            .setContentText(notificationMessage)
+
+        buildActions()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/alarm.xml b/app/src/main/res/drawable/alarm.xml
new file mode 100644
index 000000000..38409c396
--- /dev/null
+++ b/app/src/main/res/drawable/alarm.xml
@@ -0,0 +1,12 @@
+<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="M8.5,5.5a0.5,0.5 0,0 0,-1 0v3.362l-1.429,2.38a0.5,0.5 0,1 0,0.858 0.515l1.5,-2.5A0.5,0.5 0,0 0,8.5 9z"
+      android:fillColor="?android:colorForeground"/>
+  <path
+      android:pathData="M6.5,0a0.5,0.5 0,0 0,0 1L7,1v1.07a7.001,7.001 0,0 0,-3.273 12.474l-0.602,0.602a0.5,0.5 0,0 0,0.707 0.708l0.746,-0.746A6.97,6.97 0,0 0,8 16a6.97,6.97 0,0 0,3.422 -0.892l0.746,0.746a0.5,0.5 0,0 0,0.707 -0.708l-0.601,-0.602A7.001,7.001 0,0 0,9 2.07L9,1h0.5a0.5,0.5 0,0 0,0 -1zM7.538,3.018a6,6 0,0 1,0.924 0,6 6,0 1,1 -0.924,0M0,3.5c0,0.753 0.333,1.429 0.86,1.887A8.04,8.04 0,0 1,4.387 1.86,2.5 2.5,0 0,0 0,3.5M13.5,1c-0.753,0 -1.429,0.333 -1.887,0.86a8.04,8.04 0,0 1,3.527 3.527A2.5,2.5 0,0 0,13.5 1"
+      android:fillColor="?android:colorForeground"/>
+</vector>
diff --git a/app/src/main/res/drawable/exclamation_triangle_fill.xml b/app/src/main/res/drawable/exclamation_triangle_fill.xml
new file mode 100644
index 000000000..a66187d40
--- /dev/null
+++ b/app/src/main/res/drawable/exclamation_triangle_fill.xml
@@ -0,0 +1,9 @@
+<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="M8.982,1.566a1.13,1.13 0,0 0,-1.96 0L0.165,13.233c-0.457,0.778 0.091,1.767 0.98,1.767h13.713c0.889,0 1.438,-0.99 0.98,-1.767zM8,5c0.535,0 0.954,0.462 0.9,0.995l-0.35,3.507a0.552,0.552 0,0 1,-1.1 0L7.1,5.995A0.905,0.905 0,0 1,8 5m0.002,6a1,1 0,1 1,0 2,1 1,0 0,1 0,-2"
+      android:fillColor="?android:colorForeground"/>
+</vector>
diff --git a/app/src/main/res/layout/card_medicine.xml b/app/src/main/res/layout/card_medicine.xml
index 19d7b5ce2..a34b1565e 100644
--- a/app/src/main/res/layout/card_medicine.xml
+++ b/app/src/main/res/layout/card_medicine.xml
@@ -43,8 +43,7 @@
                 android:id="@+id/medicineName"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:textStyle="bold" />
+                android:layout_gravity="center_vertical" />

             <TextView
                 android:id="@+id/remindersSummary"
diff --git a/app/src/main/res/layout/notification.xml b/app/src/main/res/layout/notification.xml
new file mode 100644
index 000000000..7c6406532
--- /dev/null
+++ b/app/src/main/res/layout/notification.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:theme="@style/Theme.MedTimer">
+
+    <TextView
+        android:id="@+id/notificationTitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:drawablePadding="8dp"
+        android:drawableTint="@android:color/holo_red_dark"
+        android:text="@string/medicine_name"
+        tools:ignore="UseCompatTextViewDrawableXml" />
+
+    <Button
+        android:id="@+id/takenButton"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="30dp"
+        android:contentDescription="@string/taken"
+        android:drawableStart="@drawable/check2_circle"
+        android:text="@string/taken"
+        android:textAllCaps="false" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/skippedButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="10dp"
+            android:layout_weight="1"
+            android:drawableStart="@drawable/x_circle"
+            android:text="@string/skipped"
+            android:textAllCaps="false"
+            tools:ignore="ButtonStyle" />
+
+        <Button
+            android:id="@+id/snoozeButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="10dp"
+            android:layout_weight="1"
+            android:drawableStart="@drawable/alarm"
+            android:text="@string/snooze"
+            android:textAllCaps="false"
+            tools:ignore="ButtonStyle" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index fcdd3623f..55e9e16aa 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -19,8 +19,6 @@
         <item quantity="other">%1$d Erinnerungen\n%2$s</item>
     </plurals>
     <string name="notification_title">Erinnerung an ein Medikament</string>
-    <string name="notification_content_blank">Es ist %1$s Uhr - Zeit, %2$s%3$s%4$s einzunehmen</string>
-    <string name="notification_content">Es ist %1$s Uhr - Zeit, %2$s von %3$s%4$s einzunehmen</string>
     <string name="taken">Eingenommen</string>
     <string name="skipped">Übersprungen</string>
     <string name="recent_events">Kürzliche Ereignisse</string>
@@ -186,7 +184,7 @@
     <string name="once_below_threshold">Einmal beim Erreichen des Schwellwerts</string>
     <string name="always_below_threshold">Immer, wenn der Schwellwert unterschritten wird</string>
     <string name="out_of_stock_notification">Es ist nur noch %2$s von %1$s übrig!\nBitte füllen Sie das Medikament bald nach.</string>
-    <string name="medicine_stock_string">%1$s übrig%2$s</string>
+    <string name="medicine_stock_string">%1$s übrig</string>
     <string name="out_of_stock_notification_title">Erinnerung an Medikamentenvorrat</string>
     <string name="medicine_stock">Medikamentenvorrat</string>
     <string name="amount">Anzahl</string>
@@ -217,4 +215,5 @@
     <string name="interval_reminder_type_hint">Erinnert nach einer bestimmten Zeit, die nach der letzten Erinnerung vergangen ist.</string>
     <string name="sticky_on_lockscreen">Dauerhafte Erinnerungen auf dem Sperrbildschirm</string>
     <string name="sticky_on_lockscreen_summary">Erinnerungen können nicht über den Sperrbildschirm, sondern nur über die Benachrichtigungsleiste verworfen werden</string>
+    <string name="big_notifications">Große Benachrichtigungsknöpfe</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 1b5098a4d..2acd303a0 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -20,8 +20,6 @@
         <item quantity="other">%1$d recordatorios\n%2$s</item>
     </plurals>
     <string name="notification_title">Recordatorio de medicación</string>
-    <string name="notification_content_blank">Son las %1$s - hora de tomar %2$s%3$s%4$s</string>
-    <string name="notification_content">Son las %1$s - hora de tomar %2$s de %3$s%4$s</string>
     <string name="taken">Tomado</string>
     <string name="skipped">Omitido</string>
     <string name="recent_events">Eventos recientes</string>
@@ -191,7 +189,7 @@
     <string name="once_below_threshold">Una vez al caer por debajo del umbral</string>
     <string name="always_below_threshold">Siempre que esté por debajo del umbral</string>
     <string name="out_of_stock_notification">¡Sólo quedan %2$s de %1$s!\nConsidere rellenar la medicina pronto.</string>
-    <string name="medicine_stock_string">%1$s restantes%2$s</string>
+    <string name="medicine_stock_string">%1$s restantes</string>
     <string name="out_of_stock_notification_title">Recordatorio de medicamentos agotados</string>
     <string name="medicine_stock">Stock de medicamentos</string>
     <string name="amount">Cantidad</string>
@@ -222,4 +220,5 @@
     <string name="interval_reminder_type_hint">Recuerda una vez transcurrido un tiempo especificado desde el último recordatorio.</string>
     <string name="sticky_on_lockscreen">Recordatorios permanentes en la pantalla de bloqueo</string>
     <string name="sticky_on_lockscreen_summary">Los recordatorios no se pueden descartar desde la pantalla de bloqueo, sólo desde el cajón de notificaciones</string>
+    <string name="big_notifications">Botones de notificación grandes</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 374a9b407..6c4544694 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -20,8 +20,6 @@
         <item quantity="other">%1$d rappels\n%2$s</item>
     </plurals>
     <string name="notification_title">Rappel de médicaments</string>
-    <string name="notification_content_blank">Il est %1$s: il est temps de prendre %2$s%3$s%4$s</string>
-    <string name="notification_content">Il est %1$s: il est temps de prendre %2$s de %3$s%4$s</string>
     <string name="taken">Pris</string>
     <string name="skipped">Sauté</string>
     <string name="recent_events">Événements récents</string>
@@ -191,7 +189,7 @@
     <string name="once_below_threshold">Une fois lors du passage en dessous du seuil</string>
     <string name="always_below_threshold">Toujours en dessous du seuil</string>
     <string name="out_of_stock_notification">Il ne reste plus que %2$s de %1$s!\nConsidérez de renouveler le médicament bientôt.</string>
-    <string name="medicine_stock_string">%1$s restants%2$s</string>
+    <string name="medicine_stock_string">%1$s restants</string>
     <string name="out_of_stock_notification_title">Rappel de la réserve de médicaments</string>
     <string name="medicine_stock">Réserve de médicaments</string>
     <string name="amount">Numbre</string>
@@ -222,4 +220,5 @@
     <string name="interval_reminder_type_hint">Rappelle après un délai spécifié après le dernier rappel.</string>
     <string name="sticky_on_lockscreen">Rappels persistants sur l&apos;écran de verrouillage</string>
     <string name="sticky_on_lockscreen_summary">Les rappels ne peuvent pas être supprimés à partir de l&apos;écran de verrouillage, mais uniquement à partir du tiroir de notifications</string>
+    <string name="big_notifications">Gros boutons de notification</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 0d733c6aa..d8ec0fd1a 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -20,8 +20,6 @@
         <item quantity="other">%1$d promemoria\n%2$s</item>
     </plurals>
     <string name="notification_title">Promemoria per i medicinali</string>
-    <string name="notification_content_blank">Sono le %1$s : è ora di prendere %2$s%3$s%4$s</string>
-    <string name="notification_content">Sono le %1$s: è ora di prendere %2$s di %3$s%4$s</string>
     <string name="taken">Preso</string>
     <string name="skipped">Saltato</string>
     <string name="recent_events">Eventi recenti</string>
@@ -191,7 +189,7 @@
     <string name="once_below_threshold">Una volta quando si scende sotto la soglia</string>
     <string name="always_below_threshold">Sempre quando è al di sotto della soglia</string>
     <string name="out_of_stock_notification">È rimasto solo il %2$s di %1$s!\nEffettua una nuova scorta del medicinale.</string>
-    <string name="medicine_stock_string">%1$s rimaste%2$s</string>
+    <string name="medicine_stock_string">%1$s rimaste</string>
     <string name="out_of_stock_notification_title">Promemoria per fare scorta di medicinali</string>
     <string name="medicine_stock">Scorta di medicinali</string>
     <string name="amount">Quantità</string>
@@ -222,4 +220,5 @@
     <string name="interval_reminder_type_hint">Richiama dopo un determinato periodo di tempo dall&apos;ultimo richiamo.</string>
     <string name="sticky_on_lockscreen">Promemoria persistenti sulla schermata di blocco</string>
     <string name="sticky_on_lockscreen_summary">I promemoria non possono essere eliminati dalla schermata di blocco, ma solo dal cassetto delle notifiche</string>
+    <string name="big_notifications">Grandi pulsanti di notifica</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index bd64f3dd1..43de31a6b 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -19,8 +19,6 @@
         <item quantity="other">%1$d herinneringen\n%2$s</item>
     </plurals>
     <string name="notification_title">Herinneringen van de behandeling</string>
-    <string name="notification_content_blank">Het is %1$s - tijd om %2$s%3$s%4$s te nemen</string>
-    <string name="notification_content">Het is %1$s - tijd om %2$s van %3$s%4$s te nemen</string>
     <string name="taken">Ingenomen</string>
     <string name="skipped">Overgeslagen</string>
     <string name="recent_events">Recente herinneringen</string>
@@ -186,7 +184,7 @@
     <string name="once_below_threshold">Eenmaal bij het dalen onder de drempel</string>
     <string name="always_below_threshold">Altijd wanneer onder drempel</string>
     <string name="out_of_stock_notification">Er is nog maar %2$s van %1$s over!\nOverweeg om het medicijn snel bij te vullen.</string>
-    <string name="medicine_stock_string">%1$s over%2$s</string>
+    <string name="medicine_stock_string">%1$s over</string>
     <string name="out_of_stock_notification_title">Herinnering aan behandelingsvoorraad</string>
     <string name="medicine_stock">Behandelingsvoorraad</string>
     <string name="amount">Hoeveelheid</string>
@@ -217,4 +215,5 @@
     <string name="interval_reminder_type_hint">Herinnert nadat een opgegeven tijd is verstreken na de laatste herinnering.</string>
     <string name="sticky_on_lockscreen">Aanhoudende herinneringen op het vergrendelscherm</string>
     <string name="sticky_on_lockscreen_summary">Herinneringen kunnen niet worden verwijderd vanaf het vergrendelscherm, alleen vanuit de meldingenlade</string>
+    <string name="big_notifications">Grote meldingsknoppen</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index c4b8b2154..c7fe4c6ec 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -29,8 +29,6 @@
     <string name="delete">Usuń</string>
     <string name="cancel">Anuluj</string>
     <string name="confirm">Potwierdź</string>
-    <string name="notification_content_blank">Jest %1$s - czas wziąć %2$s%3$s%4$s</string>
-    <string name="notification_content">Jest %1$s - czas wziąć %2$s z %3$s%4$s</string>
     <string name="taken">Przyjęto</string>
     <string name="skipped">Pominięto</string>
     <string name="are_you_sure_delete_reminder">Czy na pewno chcesz usunąć to przypomnienie?</string>
@@ -134,7 +132,7 @@
     <string name="create_reminder">Utwórz przypomnienie</string>
     <string name="every_interval">Co %s</string>
     <string name="always_below_threshold">Zawsze, gdy poniżej progu</string>
-    <string name="medicine_stock_string">%1$s pozostało%2$s</string>
+    <string name="medicine_stock_string">%1$s pozostało</string>
     <string name="out_of_stock_notification_title">Przypomnienie o wyczerpaniu zapasów leków</string>
     <string name="medicine_stock">Zapasy leków</string>
     <string name="out_of_stock_reminder">Przypomnienie o wyczerpaniu zapasów</string>
@@ -228,4 +226,5 @@
     <string name="interval_reminder_type_hint">Przypomina po upływie określonego czasu od ostatniego przypomnienia.</string>
     <string name="sticky_on_lockscreen">Stałe przypomnienia na ekranie blokady</string>
     <string name="sticky_on_lockscreen_summary">Przypomnień nie można odrzucić z ekranu blokady, a jedynie z szuflady powiadomień</string>
+    <string name="big_notifications">Duże przyciski powiadomień</string>
 </resources>
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 72c8d6c67..5f0c90663 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -21,8 +21,6 @@
         <item quantity="other">%1$d напоминаний\n%2$s</item>
     </plurals>
     <string name="notification_title">Напоминание о лекарстве</string>
-    <string name="notification_content_blank">Сейчас %1$s - время принять %2$s%3$s%4$s</string>
-    <string name="notification_content">Сейчас %1$s - время принять %2$s %3$s%4$s</string>
     <string name="taken">Принято</string>
     <string name="skipped">Пропущено</string>
     <string name="recent_events">Последние события</string>
@@ -193,7 +191,7 @@
     <string name="once_below_threshold">Один раз при падении ниже порога</string>
     <string name="always_below_threshold">Всегда, когда ниже порога</string>
     <string name="out_of_stock_notification">Осталось всего %2$s от %1$s!\nПодумайте о том, чтобы пополнить запасы лекарства в ближайшее время.</string>
-    <string name="medicine_stock_string">Осталось %1$s %2$s</string>
+    <string name="medicine_stock_string">Осталось %1$s</string>
     <string name="out_of_stock_notification_title">Напоминание об отсутствии лекарств на складе</string>
     <string name="medicine_stock">Запас медикаментов</string>
     <string name="amount">Сумма</string>
@@ -224,4 +222,5 @@
     <string name="interval_reminder_type_hint">Напоминает по истечении заданного времени после последнего напоминания.</string>
     <string name="sticky_on_lockscreen">Постоянные напоминания на экране блокировки</string>
     <string name="sticky_on_lockscreen_summary">Напоминания нельзя отменить на экране блокировки, только в ящике уведомлений</string>
+    <string name="big_notifications">Большие кнопки уведомлений</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml
index 9f82aa80e..240cce44d 100644
--- a/app/src/main/res/values-ta/strings.xml
+++ b/app/src/main/res/values-ta/strings.xml
@@ -28,8 +28,6 @@
         <item quantity="other">%1$d நினைவூட்டல்கள்\n %2$s</item>
     </plurals>
     <string name="notification_title">மருந்து நினைவூட்டல்</string>
-    <string name="notification_content_blank">இது %1$s - %2$s %3$s %4$s ஐ எடுக்க நேரம்</string>
-    <string name="notification_content">இது %1$s - %2$s %3$s %4$s ஐ எடுக்க நேரம்</string>
     <string name="taken">எடுக்கப்பட்டது</string>
     <string name="skipped">தவிர்க்கப்பட்டது</string>
     <string name="recent_events">அண்மைக் கால நிகழ்வுகள்</string>
@@ -175,7 +173,7 @@
     <string name="once_below_threshold">ஒருமுறை வாசலுக்கு கீழே விழும்போது</string>
     <string name="always_below_threshold">எப்போதும் வாசலுக்கு கீழே இருக்கும்போது</string>
     <string name="out_of_stock_notification">%2$s மட்டுமே %1$s உள்ளன!\n விரைவில் மருந்தை மீண்டும் நிரப்புவதைக் கவனியுங்கள்.</string>
-    <string name="medicine_stock_string">%1$s இடது%2$s</string>
+    <string name="medicine_stock_string">%1$s இடது</string>
     <string name="out_of_stock_notification_title">பங்கு நினைவூட்டலுக்கு வெளியே மருத்துவம்</string>
     <string name="medicine_stock">மருந்து பங்கு</string>
     <string name="amount">தொகை</string>
@@ -218,4 +216,5 @@
     <string name="interval_reminder_type_hint">கடைசி நினைவூட்டலுக்குப் பிறகு குறிப்பிட்ட நேரம் கடந்ததும் நினைவூட்டுகிறது.</string>
     <string name="sticky_on_lockscreen">பூட்டுத் திரையில் நிலையான நினைவூட்டல்கள்</string>
     <string name="sticky_on_lockscreen_summary">நினைவூட்டல்களை பூட்டுத் திரையில் இருந்து நீக்க முடியாது, அறிவிப்புகள் இழுப்பறையில் இருந்து மட்டுமே நீக்க முடியும்</string>
+    <string name="big_notifications">பெரிய அறிவிப்பு பொத்தான்கள்</string>
 </resources>
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index caa5d2e98..14ed92245 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -19,8 +19,6 @@
         <item quantity="other">%1$d hatırlatıcı\n%2$s</item>
     </plurals>
     <string name="notification_title">İlaç hatırlatıcısı</string>
-    <string name="notification_content_blank">Şu anda %1$s - %2$s%3$s ilacından almanın zamanı geldi%4$s</string>
-    <string name="notification_content">Şu anda %1$s - %3$s ilacından %2$s almanın zamanı geldi%4$s</string>
     <string name="taken">Alındı</string>
     <string name="skipped">Atlandı</string>
     <string name="recent_events">Son etkinlikler</string>
@@ -186,7 +184,7 @@
     <string name="once_below_threshold">Eşiğin altına düştüğünde bir kez</string>
     <string name="always_below_threshold">Her zaman eşiğin altında olduğunda</string>
     <string name="out_of_stock_notification">%1$s&apos;dan sadece %2$s kaldı!\nİlacı yakında yeniden doldurmayı düşünün.</string>
-    <string name="medicine_stock_string">%1$s kaldı%2$s</string>
+    <string name="medicine_stock_string">%1$s kaldı</string>
     <string name="out_of_stock_notification_title">İlaç stokta yok hatırlatması</string>
     <string name="medicine_stock">İlaç stoğu</string>
     <string name="amount">Miktar</string>
@@ -217,4 +215,5 @@
     <string name="interval_reminder_type_hint">Son hatırlatmadan sonra belirli bir süre geçtikten sonra hatırlatır.</string>
     <string name="sticky_on_lockscreen">Kilit ekranında kalıcı hatırlatıcılar</string>
     <string name="sticky_on_lockscreen_summary">Hatırlatıcılar kilit ekranından kapatılamaz, sadece bildirim çekmecesinden kapatılabilir</string>
+    <string name="big_notifications">Büyük bildirim düğmeleri</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 78a096a16..1ab9257ef 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -19,8 +19,6 @@
         <item quantity="many">%1$d нагадування\n%2$s</item>
         <item quantity="other">%1$d нагадування\n%2$s</item>
     </plurals>
-    <string name="notification_content">Зараз %1$s - час прийняти %2$s з %3$s%4$s</string>
-    <string name="notification_content_blank">Зараз %1$s - час прийняти %2$s%3$s%4$s</string>
     <string name="show_notifications">Показувати сповіщення</string>
     <string name="overview_events">Огляд відображених подій</string>
     <string name="four_hours">4 години</string>
@@ -172,7 +170,7 @@
     <string name="once_below_threshold">Один раз при падінні нижче порогового значення</string>
     <string name="always_below_threshold">Завжди, коли нижче порогу</string>
     <string name="out_of_stock_notification">Залишилося лише %2$s від %1$s!\nПодумайте про те, щоб поповнити запас ліків найближчим часом.</string>
-    <string name="medicine_stock_string">%1$s left%2$s</string>
+    <string name="medicine_stock_string">Залишилося %1$s</string>
     <string name="out_of_stock_notification_title">Нагадування про відсутність ліків на складі</string>
     <string name="medicine_stock">Запас медикаментів</string>
     <string name="amount">Сума</string>
@@ -227,4 +225,5 @@
     <string name="interval_reminder_type_hint">Нагадує через певний час після останнього нагадування.</string>
     <string name="sticky_on_lockscreen">Постійні нагадування на екрані блокування</string>
     <string name="sticky_on_lockscreen_summary">Нагадування не можна відкинути з екрана блокування, тільки зі скриньки сповіщень</string>
+    <string name="big_notifications">Великі кнопки сповіщень</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 2cf655b43..113e4f924 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -18,8 +18,6 @@
         <item quantity="other">共有 %1$d 条提醒\n%2$s</item>
     </plurals>
     <string name="notification_title">服药提醒</string>
-    <string name="notification_content_blank">现在是 %1$s - 请服用 %2$s%3$s%4$s</string>
-    <string name="notification_content">现在是 %1$s - 请服用 %2$s 剂量的 %3$s%4$s</string>
     <string name="taken">已服用</string>
     <string name="skipped">已跳过</string>
     <string name="recent_events">近期服药记录</string>
@@ -181,7 +179,7 @@
     <string name="once_below_threshold">低于设定值时提醒一次</string>
     <string name="always_below_threshold">低于设定值时总是提醒</string>
     <string name="out_of_stock_notification">%1$s 只剩下 %2$s 了！\n请考虑马上重新配药。</string>
-    <string name="medicine_stock_string">还剩 %1$s %2$s</string>
+    <string name="medicine_stock_string">还剩 %1$s</string>
     <string name="out_of_stock_notification_title">药品低余量提醒</string>
     <string name="medicine_stock">药品余量</string>
     <string name="amount">数量</string>
@@ -212,4 +210,5 @@
     <string name="interval_reminder_type_hint">在最后一次提醒后的指定时间后提醒。</string>
     <string name="sticky_on_lockscreen">锁屏上的持续提醒</string>
     <string name="sticky_on_lockscreen_summary">不能从锁屏解除提醒，只能从通知抽屉解除提醒</string>
+    <string name="big_notifications">大通知按钮</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 356f1796e..6821bf168 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,8 +20,6 @@
         <item quantity="other">%1$d reminders\n%2$s</item>
     </plurals>
     <string name="notification_title">Medicine reminder</string>
-    <string name="notification_content_blank">It is %1$s - time to take %2$s%3$s%4$s</string>
-    <string name="notification_content">It is %1$s - time to take %2$s of %3$s%4$s</string>
     <string name="taken">Taken</string>
     <string name="skipped">Skipped</string>
     <string name="recent_events">Recent events</string>
@@ -190,7 +188,7 @@
     <string name="once_below_threshold">Once when falling below threshold</string>
     <string name="always_below_threshold">Always when below threshold</string>
     <string name="out_of_stock_notification">Only %2$s of %1$s left!\nConsider refilling the medicine soon.</string>
-    <string name="medicine_stock_string">%1$s left%2$s</string>
+    <string name="medicine_stock_string">%1$s left</string>
     <string name="out_of_stock_notification_title">Medicine out of stock reminder</string>
     <string name="medicine_stock">Medicine stock</string>
     <string name="amount">Amount</string>
@@ -221,4 +219,5 @@
     <string name="interval_reminder_type_hint">Reminds after a specified time has elapsed after the last reminder.</string>
     <string name="sticky_on_lockscreen">Persistent reminders on lock screen</string>
     <string name="sticky_on_lockscreen_summary">Reminders cannot be dismissed from the lock screen, only from the notifications drawer</string>
+    <string name="big_notifications">Big notification buttons</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/xml/display_settings.xml b/app/src/main/res/xml/display_settings.xml
index 44780d521..dd78ff4a2 100644
--- a/app/src/main/res/xml/display_settings.xml
+++ b/app/src/main/res/xml/display_settings.xml
@@ -5,8 +5,14 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:defaultValue="false"
-        android:title="@string/use_relative_date_time"
+        android:title="@string/big_notifications"
+        app:key="big_notifications" />
+    <SwitchPreferenceCompat
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:defaultValue="false"
         android:summary="@string/use_relative_date_time_summary"
+        android:title="@string/use_relative_date_time"
         app:key="use_relative_date_time" />
     <ListPreference
         android:layout_width="wrap_content"

diff --git a/app/src/test/java/com/futsch1/medtimer/ReminderWorkUnitTest.java b/app/src/test/java/com/futsch1/medtimer/ReminderWorkUnitTest.java
index 9175ecbbd..661cdb4b0 100644
--- a/app/src/test/java/com/futsch1/medtimer/ReminderWorkUnitTest.java
+++ b/app/src/test/java/com/futsch1/medtimer/ReminderWorkUnitTest.java
@@ -99,7 +99,6 @@ public void setUp() {
         when(mockApplication.getSharedPreferences(anyString(), anyInt())).thenReturn(mockSharedPreferences);
         when(mockApplication.getString(R.string.notification_title)).thenReturn("NotificationTitle");
         when(mockApplication.getString(R.string.taken)).thenReturn("NotificationTaken");
-        when(mockApplication.getString(eq(R.string.notification_content), any(Object[].class))).thenReturn("NotificationContent");
         mockNotificationManager = mock(NotificationManager.class);
         when(mockApplication.getSystemService(NotificationManager.class)).thenReturn(mockNotificationManager);
     }
@@ -164,6 +163,7 @@ public void testDoWorkNotifications() {
                  when(mock.setCategory(Notification.CATEGORY_REMINDER)).thenReturn(mock);
                  when(mock.setLargeIcon((Bitmap) null)).thenReturn(mock);
                  when(mock.addAction(eq(R.drawable.check2_circle), eq("NotificationTaken"), any())).thenReturn(mock());
+                 when(mock.build()).thenReturn(new Notification());
              });
              MockedConstruction<MedicineIcons> ignored3 = mockConstruction(MedicineIcons.class, (mock, context) -> when(mock.getIconBitmap(0)).thenReturn(null));
              MockedStatic<WorkManagerAccess> mockedWorkManagerAccess = mockStatic(WorkManagerAccess.class);
@@ -215,6 +215,7 @@ public void testDoWorkNewReminder() {
                  when(mock.setLargeIcon((Bitmap) null)).thenReturn(mock);
                  when(mock.setCategory(Notification.CATEGORY_REMINDER)).thenReturn(mock);
                  when(mock.addAction(eq(R.drawable.check2_circle), eq("NotificationTaken"), any())).thenReturn(mock());
+                 when(mock.build()).thenReturn(new Notification());
              });
              MockedConstruction<MedicineIcons> ignored3 = mockConstruction(MedicineIcons.class, (mock, context) -> when(mock.getIconBitmap(16)).thenReturn(null));
              MockedStatic<WorkManagerAccess> mockedWorkManagerAccess = mockStatic(WorkManagerAccess.class);