From c5b976a04ac73609ddb0bd0dc2a9274e7ec769cc Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski <janne@kuschku.de>
Date: Wed, 30 Aug 2023 06:09:46 +0200
Subject: [PATCH] fix: warnings raised by updating dependencies

---
 app/build.gradle.kts                          |   6 +-
 app/src/main/AndroidManifest.xml              |   1 +
 .../QuasseldroidNotificationManager.kt        |  22 +-
 .../quasseldroid/ui/chat/ChatActivity.kt      | 405 +++++++++++-------
 .../PreferenceDialogFragmentCompat.java       |   3 +-
 .../quasseldroid/util/ui/view/ShadowView.kt   |   1 -
 app/src/main/res/drawable/ic_monochrome.xml   |  26 ++
 app/src/main/res/mipmap-v26/ic_launcher.xml   |   1 +
 .../kotlin/justjanne.repositories.gradle.kts  |   5 -
 gradle/libs.versions.toml                     |   6 +-
 lib/build.gradle.kts                          |   4 +-
 .../integration/AliasManagerTest.kt           |   8 +-
 .../integration/BufferViewConfigTest.kt       |   6 +-
 .../integration/SampleIntegrationTest.kt      |   4 +-
 .../integration/SignedIdNameTests.kt          |   2 +-
 .../serializer/BoolSerializerTest.kt          |   4 +-
 .../serializer/BufferInfoSerializerTest.kt    |   4 +-
 .../serializer/ByteArraySerializerTest.kt     |   4 +-
 .../serializer/ByteSerializerTest.kt          |   4 +-
 .../serializer/CharSerializerTest.kt          |   4 +-
 .../serializer/DateTimeSerializerTest.kt      |  10 +-
 .../serializer/HostAddressSerializerTest.kt   |   4 +-
 .../primitive/serializer/IntSerializerTest.kt |   4 +-
 .../serializer/LongSerializerTest.kt          |   4 +-
 .../serializer/MessageSerializerTest.kt       |  12 +-
 .../serializer/ProtocolInfoSerializerTest.kt  |   4 +-
 .../serializer/ShortSerializerTest.kt         |   4 +-
 .../serializer/StringSerializerTest.kt        |   6 +-
 .../libquassel/quassel/BufferTypeTest.kt      |  54 +--
 .../quassel/syncables/AliasManagerTest.kt     |   2 +-
 .../quassel/syncables/BufferSyncerTest.kt     |   2 +-
 .../quassel/syncables/BufferViewConfigTest.kt |   8 +-
 .../syncables/BufferViewManagerTest.kt        |   2 +-
 .../syncables/HighlightRuleManagerTest.kt     |   8 +-
 .../quassel/syncables/IdentityTest.kt         |   2 +-
 .../syncables/IgnoreListManagerTest.kt        |   2 +-
 .../quassel/syncables/NetworkConfigTest.kt    |   2 +-
 .../quassel/syncables/NetworkTest.kt          |  12 +-
 .../syncables/interfaces/INetworkInfoTest.kt  |   4 +-
 .../libquassel/util/ExpressionMatchTest.kt    |   6 +-
 .../de/kuschku/libquassel/util/TestSession.kt |  34 +-
 .../libquassel/util/irc/HostmaskHelperTest.kt |   4 +-
 .../libquassel/util/nio/WrappedChannelTest.kt |   4 +-
 .../util/rxjava/ReusableUnicastSubjectTest.kt |   4 +-
 lint.xml                                      |   3 +-
 .../collectors/ConfigurationCollector.kt      |   2 +
 viewmodel/build.gradle.kts                    |   3 +-
 .../viewmodel/ChatViewModelTest.kt            |   4 +-
 48 files changed, 454 insertions(+), 276 deletions(-)
 create mode 100644 app/src/main/res/drawable/ic_monochrome.xml
 delete mode 100644 gradle/convention/src/main/kotlin/justjanne.repositories.gradle.kts

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9b254dd23..f05695102 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -124,14 +124,16 @@ dependencies {
   implementation(libs.dagger.android.core)
   implementation(libs.dagger.android.support)
 
-  testImplementation(libs.junit)
+  testImplementation(libs.junit.api)
+  testRuntimeOnly(libs.junit.engine)
   testImplementation(libs.androidx.test.core)
   testImplementation(libs.robolectric) {
     exclude(group = "org.threeten", module = "threetenbp")
     exclude(group = "com.google.auto.service", module = "auto-service")
   }
 
-  androidTestImplementation(libs.junit)
+  androidTestImplementation(libs.junit.api)
+  androidTestRuntimeOnly(libs.junit.engine)
   androidTestImplementation(libs.androidx.test.espresso.core)
   androidTestImplementation(libs.androidx.test.espresso.contrib)
   androidTestImplementation(libs.androidx.test.junit)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ab32d2076..0184736b7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -30,6 +30,7 @@
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
   <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
 
   <application
     android:name="de.kuschku.quasseldroid.Quasseldroid"
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasseldroidNotificationManager.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasseldroidNotificationManager.kt
index e4f651347..e26ce8a87 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasseldroidNotificationManager.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasseldroidNotificationManager.kt
@@ -19,6 +19,7 @@
 
 package de.kuschku.quasseldroid.service
 
+import android.Manifest
 import android.annotation.TargetApi
 import android.app.Notification
 import android.app.NotificationChannel
@@ -26,11 +27,13 @@ import android.app.NotificationManager
 import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.drawable.Drawable
 import android.net.Uri
 import android.os.Build
+import androidx.core.app.ActivityCompat
 import androidx.core.app.NotificationCompat
 import androidx.core.app.NotificationManagerCompat
 import androidx.core.app.Person
@@ -63,7 +66,8 @@ class QuasseldroidNotificationManager @Inject constructor(private val context: C
 
   @TargetApi(Build.VERSION_CODES.O)
   private fun prepareChannels() {
-    val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+    val notificationManager =
+      context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
     notificationManager.createNotificationChannels(
       listOf(
         NotificationChannel(
@@ -109,9 +113,11 @@ class QuasseldroidNotificationManager @Inject constructor(private val context: C
     return bitmap
   }
 
-  fun notificationMessage(notificationSettings: NotificationSettings, buffer: NotificationBuffer,
-                          selfInfo: SelfInfo, notifications: List<NotificationMessage>,
-                          isLoud: Boolean, isConnected: Boolean): Handle {
+  fun notificationMessage(
+    notificationSettings: NotificationSettings, buffer: NotificationBuffer,
+    selfInfo: SelfInfo, notifications: List<NotificationMessage>,
+    isLoud: Boolean, isConnected: Boolean
+  ): Handle {
     val pendingIntentOpen = PendingIntent.getActivity(
       context.applicationContext,
       System.currentTimeMillis().toInt(),
@@ -279,7 +285,13 @@ class QuasseldroidNotificationManager @Inject constructor(private val context: C
   }
 
   fun notify(handle: Handle) {
-    notificationManagerCompat.notify(handle.id, handle.builder.build())
+    if (ActivityCompat.checkSelfPermission(
+        context.applicationContext,
+        Manifest.permission.POST_NOTIFICATIONS
+      ) == PackageManager.PERMISSION_GRANTED
+    ) {
+      notificationManagerCompat.notify(handle.id, handle.builder.build())
+    }
   }
 
   fun remove(handle: Handle) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
index 32734dcb6..9e971b1d9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
@@ -19,11 +19,13 @@
 
 package de.kuschku.quasseldroid.ui.chat
 
+import android.Manifest
 import android.annotation.SuppressLint
 import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.content.SharedPreferences
+import android.content.pm.PackageManager
 import android.os.Build
 import android.os.Bundle
 import android.os.PersistableBundle
@@ -35,7 +37,9 @@ import android.view.MenuItem
 import android.view.View
 import android.widget.EditText
 import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.ActionBarDrawerToggle
+import androidx.core.app.ActivityCompat
 import androidx.core.view.GravityCompat
 import androidx.drawerlayout.widget.DrawerLayout
 import androidx.lifecycle.Observer
@@ -71,6 +75,7 @@ import de.kuschku.quasseldroid.persistence.models.Filtered
 import de.kuschku.quasseldroid.persistence.models.SslHostnameWhitelistEntry
 import de.kuschku.quasseldroid.persistence.models.SslValidityWhitelistEntry
 import de.kuschku.quasseldroid.persistence.util.AccountId
+import de.kuschku.quasseldroid.service.QuasselNotificationBackend
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.settings.NotificationSettings
@@ -142,6 +147,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
   @Inject
   lateinit var autoCompleteAdapter: AutoCompleteAdapter
 
+  @Inject
+  lateinit var notificationBackend: QuasselNotificationBackend
+
   lateinit var editorBottomSheet: DragInterceptBottomSheetBehavior<View>
 
   private val dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
@@ -155,43 +163,47 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
   private var restoredDrawerState = false
 
   fun processIntent(intent: Intent) {
-      when {
-        intent.type == "text/plain"    -> {
-          val text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
-          if (text != null) {
-            chatlineFragment?.replaceText(text)
-            binding.drawerLayout.closeDrawers()
-          }
+    when {
+      intent.type == "text/plain" -> {
+        val text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
+        if (text != null) {
+          chatlineFragment?.replaceText(text)
+          binding.drawerLayout.closeDrawers()
         }
-        intent.hasExtra(KEY_BUFFER_ID) -> {
-          chatViewModel.bufferId.onNext(BufferId(intent.getIntExtra(KEY_BUFFER_ID, -1)))
-          chatViewModel.bufferOpened.onNext(Unit)
-          if (intent.hasExtra(KEY_ACCOUNT_ID)) {
-            val accountId = AccountId(intent.getLongExtra(KEY_ACCOUNT_ID, -1L))
-            if (accountId != this.accountId) {
-              resetAccount()
-              connectToAccount(accountId)
-              startedSelection = false
-              connectedAccount = AccountId(-1L)
-              checkConnection()
-              recreate()
-            }
+      }
+
+      intent.hasExtra(KEY_BUFFER_ID) -> {
+        chatViewModel.bufferId.onNext(BufferId(intent.getIntExtra(KEY_BUFFER_ID, -1)))
+        chatViewModel.bufferOpened.onNext(Unit)
+        if (intent.hasExtra(KEY_ACCOUNT_ID)) {
+          val accountId = AccountId(intent.getLongExtra(KEY_ACCOUNT_ID, -1L))
+          if (accountId != this.accountId) {
+            resetAccount()
+            connectToAccount(accountId)
+            startedSelection = false
+            connectedAccount = AccountId(-1L)
+            checkConnection()
+            recreate()
           }
         }
-        intent.hasExtra(KEY_AUTOCOMPLETE_TEXT)                            -> {
-          chatlineFragment?.editorHelper?.appendText(
-            intent.getStringExtra(KEY_AUTOCOMPLETE_TEXT),
-            intent.getStringExtra(KEY_AUTOCOMPLETE_SUFFIX)
-          )
-          binding.drawerLayout.closeDrawers()
-        }
-        intent.hasExtra(KEY_NETWORK_ID) && intent.hasExtra(KEY_CHANNEL)   -> {
-          val networkId = NetworkId(intent.getIntExtra(KEY_NETWORK_ID, -1))
-          val channel = intent.getStringExtra(KEY_CHANNEL) ?: ""
+      }
+
+      intent.hasExtra(KEY_AUTOCOMPLETE_TEXT) -> {
+        chatlineFragment?.editorHelper?.appendText(
+          intent.getStringExtra(KEY_AUTOCOMPLETE_TEXT),
+          intent.getStringExtra(KEY_AUTOCOMPLETE_SUFFIX)
+        )
+        binding.drawerLayout.closeDrawers()
+      }
+
+      intent.hasExtra(KEY_NETWORK_ID) && intent.hasExtra(KEY_CHANNEL) -> {
+        val networkId = NetworkId(intent.getIntExtra(KEY_NETWORK_ID, -1))
+        val channel = intent.getStringExtra(KEY_CHANNEL) ?: ""
 
-          val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
+        val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
 
-          modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement().subscribe {
+        modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement()
+          .subscribe {
             it.orNull()?.also { session ->
               val info = session.bufferSyncer.find(
                 bufferName = channel,
@@ -202,9 +214,11 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
               if (info != null && !forceJoin) {
                 ChatActivity.launch(this, bufferId = info.bufferId)
               } else {
-                modelHelper.chat.chatToJoin.onNext(Optional.of(
-                  Pair(networkId, channel)
-                ))
+                modelHelper.chat.chatToJoin.onNext(
+                  Optional.of(
+                    Pair(networkId, channel)
+                  )
+                )
 
                 session.bufferSyncer.find(
                   networkId = networkId,
@@ -217,14 +231,16 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
               }
             }
           }
-        }
-        intent.hasExtra(KEY_NETWORK_ID) && intent.hasExtra(KEY_NICK_NAME) -> {
-          val networkId = NetworkId(intent.getIntExtra(KEY_NETWORK_ID, -1))
-          val channel = intent.getStringExtra(KEY_NICK_NAME)
+      }
 
-          val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
+      intent.hasExtra(KEY_NETWORK_ID) && intent.hasExtra(KEY_NICK_NAME) -> {
+        val networkId = NetworkId(intent.getIntExtra(KEY_NETWORK_ID, -1))
+        val channel = intent.getStringExtra(KEY_NICK_NAME)
 
-          modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement().subscribe {
+        val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
+
+        modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement()
+          .subscribe {
             it.orNull()?.also { session ->
               val info = session.bufferSyncer.find(
                 bufferName = channel,
@@ -238,8 +254,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                 modelHelper.allBuffers.map {
                   listOfNotNull(it.find {
                     it.networkId == networkId &&
-                    it.bufferName == channel &&
-                    it.type.hasFlag(Buffer_Type.QueryBuffer)
+                      it.bufferName == channel &&
+                      it.type.hasFlag(Buffer_Type.QueryBuffer)
                   })
                 }.filter {
                   it.isNotEmpty()
@@ -260,31 +276,32 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
               }
             }
           }
-        }
-        intent.scheme == "irc" ||
-        intent.scheme == "ircs"                                           -> {
-          val uri = intent.data
-          if (uri != null) {
-            val channelString = (uri.path.let { it ?: "" }.trimStart('/')) +
-                                (uri.fragment?.let { "#$it" }.let { it ?: "" })
-            NetworkSetupActivity.launch(
-              this,
-              network = LinkNetwork(
-                name = "",
-                server = DefaultNetworkServer(
-                  host = uri.host ?: "",
-                  port = uri.port.nullIf { it < 0 }?.toUInt()
-                         ?: if (uri.scheme == "irc") PORT_PLAINTEXT.port
-                         else PORT_SSL.port,
-                  secure = uri.scheme == "ircs"
-                )
-              ),
-              channels = channelString.split(",").toTypedArray()
-            )
-          }
+      }
+
+      intent.scheme == "irc" ||
+        intent.scheme == "ircs" -> {
+        val uri = intent.data
+        if (uri != null) {
+          val channelString = (uri.path.let { it ?: "" }.trimStart('/')) +
+            (uri.fragment?.let { "#$it" }.let { it ?: "" })
+          NetworkSetupActivity.launch(
+            this,
+            network = LinkNetwork(
+              name = "",
+              server = DefaultNetworkServer(
+                host = uri.host ?: "",
+                port = uri.port.nullIf { it < 0 }?.toUInt()
+                  ?: if (uri.scheme == "irc") PORT_PLAINTEXT.port
+                  else PORT_SSL.port,
+                secure = uri.scheme == "ircs"
+              )
+            ),
+            channels = channelString.split(",").toTypedArray()
+          )
         }
       }
-      setIntent(null)
+    }
+    setIntent(null)
   }
 
   override fun onCreate(savedInstanceState: Bundle?) {
@@ -292,7 +309,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     binding = ActivityMainBinding.inflate(layoutInflater)
     setContentView(binding.root)
 
-    chatlineFragment = supportFragmentManager.findFragmentById(R.id.fragment_chatline) as? ChatlineFragment
+    chatlineFragment =
+      supportFragmentManager.findFragmentById(R.id.fragment_chatline) as? ChatlineFragment
 
     setSupportActionBar(binding.layoutMain.layoutToolbar.toolbar)
 
@@ -338,10 +356,12 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       accountDatabase.accounts().listenDefaultFiltered(accountId, 0).toObservable()
     )
 
-    val maxBufferActivity = modelHelper.processBufferList(modelHelper.bufferViewConfig,
-                                                          filtered).map { (config, bufferList) ->
+    val maxBufferActivity = modelHelper.processBufferList(
+      modelHelper.bufferViewConfig,
+      filtered
+    ).map { (config, bufferList) ->
       val minimumActivity: Buffer_Activity = config?.minimumActivity()?.enabledValues()?.maxOrNull()
-                                             ?: Buffer_Activity.NoActivity
+        ?: Buffer_Activity.NoActivity
 
       val maxActivity: Buffer_Activity = bufferList.mapNotNull {
         it.bufferActivity.enabledValues().maxOrNull()
@@ -349,11 +369,13 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
       val hasNotifications = bufferList.any { props ->
         when {
-          props.info.type hasFlag Buffer_Type.QueryBuffer   ->
+          props.info.type hasFlag Buffer_Type.QueryBuffer ->
             props.bufferActivity hasFlag Buffer_Activity.NewMessage
+
           props.info.type hasFlag Buffer_Type.ChannelBuffer ->
             props.highlights > 0
-          else                                              -> false
+
+          else -> false
         }
       }
 
@@ -366,28 +388,36 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
     supportActionBar?.apply {
       val toggleDefault = DrawerToggleActivityDrawable(themedContext, 0)
-      val toggleOtherActivity = DrawerToggleActivityDrawable(themedContext,
-                                                             R.attr.colorTintActivity)
+      val toggleOtherActivity = DrawerToggleActivityDrawable(
+        themedContext,
+        R.attr.colorTintActivity
+      )
       val toggleNewMessage = DrawerToggleActivityDrawable(themedContext, R.attr.colorTintMessage)
       val toggleHighlight = DrawerToggleActivityDrawable(themedContext, R.attr.colorTintHighlight)
-      val toggleNotification = DrawerToggleActivityDrawable(themedContext,
-                                                            R.attr.colorTintNotification)
+      val toggleNotification = DrawerToggleActivityDrawable(
+        themedContext,
+        R.attr.colorTintNotification
+      )
       maxBufferActivity.toLiveData()
         .observe(this@ChatActivity, Observer { (activity, hasNotifications) ->
           setHomeAsUpIndicator(
             when {
               notificationSettings.showAllActivitiesInToolbar &&
-              activity == Buffer_Activity.Highlight     ->
+                activity == Buffer_Activity.Highlight ->
                 toggleHighlight
+
               notificationSettings.showAllActivitiesInToolbar &&
-              activity == Buffer_Activity.NewMessage    ->
+                activity == Buffer_Activity.NewMessage ->
                 toggleNewMessage
+
               notificationSettings.showAllActivitiesInToolbar &&
-              activity == Buffer_Activity.OtherActivity ->
+                activity == Buffer_Activity.OtherActivity ->
                 toggleOtherActivity
-              hasNotifications                          ->
+
+              hasNotifications ->
                 toggleNotification
-              else                                      ->
+
+              else ->
                 toggleDefault
             }
           )
@@ -426,16 +456,17 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     modelHelper.errors.toLiveData(BackpressureStrategy.BUFFER).observe(this, Observer { error ->
       error?.let {
         when (it) {
-          is Error.HandshakeError  -> it.message.let {
+          is Error.HandshakeError -> it.message.let {
             when (it) {
-              is HandshakeMessage.ClientInitAck     ->
+              is HandshakeMessage.ClientInitAck ->
                 if (it.coreConfigured == false)
                   CoreSetupActivity.launch(
                     this,
                     accountDatabase.accounts().findById(accountId),
                     CoreSetupData.of(it)
                   )
-              is HandshakeMessage.ClientInitReject  ->
+
+              is HandshakeMessage.ClientInitReject ->
                 MaterialDialog.Builder(this)
                   .title(R.string.label_error_init)
                   .content(Html.fromHtml(it.errorString))
@@ -448,7 +479,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .contentColorAttr(R.attr.colorTextPrimary)
                   .build()
                   .show()
-              is HandshakeMessage.CoreSetupReject   ->
+
+              is HandshakeMessage.CoreSetupReject ->
                 MaterialDialog.Builder(this)
                   .title(R.string.label_error_setup)
                   .content(Html.fromHtml(it.errorString))
@@ -461,6 +493,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .contentColorAttr(R.attr.colorTextPrimary)
                   .build()
                   .show()
+
               is HandshakeMessage.ClientLoginReject ->
                 MaterialDialog.Builder(this)
                   .title(R.string.label_error_login)
@@ -514,10 +547,12 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .contentColorAttr(R.attr.colorTextPrimary)
                   .build()
                   .show()
+
               else -> Unit // Do Nothing
             }
           }
-          is Error.SslError        -> {
+
+          is Error.SslError -> {
             it.exception.let {
               if (it == QuasselSecurityException.NoSsl) {
                 // Ssl is required but not available
@@ -547,8 +582,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   when {
                     // Certificate has expired
                     it is QuasselSecurityException.Certificate &&
-                    (it.cause is CertificateNotYetValidException ||
-                     it.cause is CertificateExpiredException)  -> {
+                      (it.cause is CertificateNotYetValidException ||
+                        it.cause is CertificateExpiredException) -> {
                       MaterialDialog.Builder(this)
                         .title(R.string.label_error_certificate)
                         .content(
@@ -556,10 +591,14 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                             getString(
                               R.string.label_error_certificate_invalid,
                               leafCertificate.sha1Fingerprint,
-                              dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notBefore.time)
-                                                         .atZone(ZoneId.systemDefault())),
-                              dateTimeFormatter.format(Instant.ofEpochMilli(leafCertificate.notAfter.time)
-                                                         .atZone(ZoneId.systemDefault()))
+                              dateTimeFormatter.format(
+                                Instant.ofEpochMilli(leafCertificate.notBefore.time)
+                                  .atZone(ZoneId.systemDefault())
+                              ),
+                              dateTimeFormatter.format(
+                                Instant.ofEpochMilli(leafCertificate.notAfter.time)
+                                  .atZone(ZoneId.systemDefault())
+                              )
                             )
                           )
                         )
@@ -590,7 +629,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                         .show()
                     }
                     // Certificate is in any other way invalid
-                    it is QuasselSecurityException.Certificate   -> {
+                    it is QuasselSecurityException.Certificate -> {
                       MaterialDialog.Builder(this)
                         .title(R.string.label_error_certificate)
                         .content(
@@ -679,45 +718,62 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
               }
             }
           }
+
           is Error.ConnectionError -> {
             it.throwable.let {
               val cause = it.cause
               when {
-                it is UnknownHostException         -> {
+                it is UnknownHostException -> {
                   val host = it.message?.replace("Host is unresolved: ", "")
 
-                  Toast.makeText(this,
-                                 getString(R.string.label_error_unknown_host, host),
-                                 Toast.LENGTH_LONG).show()
+                  Toast.makeText(
+                    this,
+                    getString(R.string.label_error_unknown_host, host),
+                    Toast.LENGTH_LONG
+                  ).show()
                 }
-                it is ProtocolVersionException     -> {
+
+                it is ProtocolVersionException -> {
                   val protocolVersion: Int = it.protocol.version.toInt()
-                  Toast.makeText(this,
-                                 getString(R.string.label_error_invalid_protocol_version,
-                                           protocolVersion),
-                                 Toast.LENGTH_LONG).show()
+                  Toast.makeText(
+                    this,
+                    getString(
+                      R.string.label_error_invalid_protocol_version,
+                      protocolVersion
+                    ),
+                    Toast.LENGTH_LONG
+                  ).show()
                 }
+
                 it is ConnectException &&
-                cause is libcore.io.ErrnoException -> {
+                  cause is libcore.io.ErrnoException -> {
                   val errorCode = OsConstants.errnoName(cause.errno)
                   val errorName = OsConstants.strerror(cause.errno)
 
-                  Toast.makeText(this,
-                                 getString(R.string.label_error_connection, errorName, errorCode),
-                                 Toast.LENGTH_LONG).show()
+                  Toast.makeText(
+                    this,
+                    getString(R.string.label_error_connection, errorName, errorCode),
+                    Toast.LENGTH_LONG
+                  ).show()
                 }
+
                 it is ConnectException && cause is ErrnoException -> {
                   val errorCode = OsConstants.errnoName(cause.errno)
                   val errorName = OsConstants.strerror(cause.errno)
 
-                  Toast.makeText(this,
-                                 getString(R.string.label_error_connection, errorName, errorCode),
-                                 Toast.LENGTH_LONG).show()
+                  Toast.makeText(
+                    this,
+                    getString(R.string.label_error_connection, errorName, errorCode),
+                    Toast.LENGTH_LONG
+                  ).show()
                 }
-                else                               -> {
-                  Toast.makeText(this,
-                                 getString(R.string.label_error_connection_closed),
-                                 Toast.LENGTH_LONG).show()
+
+                else -> {
+                  Toast.makeText(
+                    this,
+                    getString(R.string.label_error_connection_closed),
+                    Toast.LENGTH_LONG
+                  ).show()
                 }
               }
             }
@@ -734,8 +790,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       .observe(this, Observer {
         if (connectedAccount != accountId) {
           if (resources.getBoolean(R.bool.buffer_drawer_exists) &&
-              chatViewModel.bufferId.safeValue == BufferId.MAX_VALUE &&
-              !restoredDrawerState) {
+            chatViewModel.bufferId.safeValue == BufferId.MAX_VALUE &&
+            !restoredDrawerState
+          ) {
             binding.drawerLayout.openDrawer(GravityCompat.START)
           }
           connectedAccount = accountId
@@ -770,7 +827,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
     binding.layoutMain.connectionStatus.setOnClickListener {
       if (modelHelper.connectionProgress.value?.first == ConnectionState.CONNECTED
-        && modelHelper.deceptiveNetwork.value == true) {
+        && modelHelper.deceptiveNetwork.value == true
+      ) {
         DeceptiveNetworkDialog.Builder(this)
           .message(R.string.deceptive_network_freenode)
           .show()
@@ -789,13 +847,14 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
         val (state, progress, max) = connection
         when (state) {
           ConnectionState.DISCONNECTED,
-          ConnectionState.CLOSED     -> {
+          ConnectionState.CLOSED -> {
             binding.layoutMain.layoutToolbar.progressBar.visibility = View.INVISIBLE
 
             binding.layoutMain.connectionStatus.icon.setImageResource(R.drawable.ic_disconnected)
             binding.layoutMain.connectionStatus.setMode(WarningBarView.MODE_ICON)
             binding.layoutMain.connectionStatus.setText(getString(R.string.label_status_disconnected))
           }
+
           ConnectionState.CONNECTING -> {
             binding.layoutMain.layoutToolbar.progressBar.visibility = View.VISIBLE
             binding.layoutMain.layoutToolbar.progressBar.isIndeterminate = true
@@ -803,14 +862,16 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
             binding.layoutMain.connectionStatus.setMode(WarningBarView.MODE_PROGRESS)
             binding.layoutMain.connectionStatus.setText(getString(R.string.label_status_connecting))
           }
-          ConnectionState.HANDSHAKE  -> {
+
+          ConnectionState.HANDSHAKE -> {
             binding.layoutMain.layoutToolbar.progressBar.visibility = View.VISIBLE
             binding.layoutMain.layoutToolbar.progressBar.isIndeterminate = true
 
             binding.layoutMain.connectionStatus.setMode(WarningBarView.MODE_PROGRESS)
             binding.layoutMain.connectionStatus.setText(getString(R.string.label_status_handshake))
           }
-          ConnectionState.INIT       -> {
+
+          ConnectionState.INIT -> {
             binding.layoutMain.layoutToolbar.progressBar.visibility = View.VISIBLE
             // Show indeterminate when no progress has been made yet
             binding.layoutMain.layoutToolbar.progressBar.isIndeterminate = progress == 0 || max == 0
@@ -820,7 +881,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
             binding.layoutMain.connectionStatus.setMode(WarningBarView.MODE_PROGRESS)
             binding.layoutMain.connectionStatus.setText(getString(R.string.label_status_init))
           }
-          ConnectionState.CONNECTED  -> {
+
+          ConnectionState.CONNECTED -> {
             binding.layoutMain.layoutToolbar.progressBar.visibility = View.INVISIBLE
             if (deceptive && appearanceSettings.deceptiveNetworks) {
               binding.layoutMain.connectionStatus.setMode(WarningBarView.MODE_ICON)
@@ -839,13 +901,17 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       if (bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) {
         binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.END)
       } else {
-        binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END)
+        binding.drawerLayout.setDrawerLockMode(
+          DrawerLayout.LOCK_MODE_LOCKED_CLOSED,
+          GravityCompat.END
+        )
       }
 
       invalidateOptionsMenu()
     })
 
-    editorBottomSheet = DragInterceptBottomSheetBehavior.from(binding.root.findViewById(R.id.fragment_chatline))
+    editorBottomSheet =
+      DragInterceptBottomSheetBehavior.from(binding.root.findViewById(R.id.fragment_chatline))
     editorBottomSheet.state = BottomSheetBehavior.STATE_COLLAPSED
     chatlineFragment?.panelSlideListener?.let(editorBottomSheet::setBottomSheetCallback)
 
@@ -861,8 +927,10 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       }
     })
 
-    combineLatest(modelHelper.allBuffers,
-                  modelHelper.chat.chatToJoin).map { (buffers, chatToJoinOptional) ->
+    combineLatest(
+      modelHelper.allBuffers,
+      modelHelper.chat.chatToJoin
+    ).map { (buffers, chatToJoinOptional) ->
       val chatToJoin = chatToJoinOptional.orNull()
       if (chatToJoin == null) {
         emptyList()
@@ -871,8 +939,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
         listOfNotNull(buffers.find {
           it.networkId == networkId &&
-          it.bufferName == channel &&
-          it.type.hasFlag(Buffer_Type.ChannelBuffer)
+            it.bufferName == channel &&
+            it.type.hasFlag(Buffer_Type.ChannelBuffer)
         })
       }
     }.filter {
@@ -882,6 +950,28 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
         launch(this, bufferId = info.bufferId)
       }
     }
+
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+      registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
+        if (isGranted) {
+          if (modelHelper.connectionProgress.value?.first == ConnectionState.CONNECTED) {
+            notificationBackend.showConnectedNotifications()
+          }
+        }
+      }
+
+      if (ActivityCompat.checkSelfPermission(
+          applicationContext,
+          Manifest.permission.POST_NOTIFICATIONS
+        ) != PackageManager.PERMISSION_GRANTED
+      ) {
+        ActivityCompat.requestPermissions(
+          this,
+          arrayOf(Manifest.permission.POST_NOTIFICATIONS),
+          1
+        )
+      }
+    }
   }
 
   override fun onNewIntent(intent: Intent?) {
@@ -938,7 +1028,10 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     chatViewModel.onSaveInstanceState(outState)
 
     outState.putLong(KEY_CONNECTED_ACCOUNT, connectedAccount.id)
-    outState.putBoolean(KEY_OPEN_DRAWER_START, binding.drawerLayout.isDrawerOpen(GravityCompat.START))
+    outState.putBoolean(
+      KEY_OPEN_DRAWER_START,
+      binding.drawerLayout.isDrawerOpen(GravityCompat.START)
+    )
     outState.putBoolean(KEY_OPEN_DRAWER_END, binding.drawerLayout.isDrawerOpen(GravityCompat.END))
   }
 
@@ -959,29 +1052,33 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
   override fun onCreateOptionsMenu(menu: Menu?): Boolean {
     val nickCountDrawableSize = resources.getDimensionPixelSize(R.dimen.size_nick_count)
-    val nickCountDrawableColor = binding.layoutMain.layoutToolbar.toolbar.context.theme.styledAttributes(
-      androidx.appcompat.R.attr.colorControlNormal
-    ) { getColor(0, 0) }
+    val nickCountDrawableColor =
+      binding.layoutMain.layoutToolbar.toolbar.context.theme.styledAttributes(
+        androidx.appcompat.R.attr.colorControlNormal
+      ) { getColor(0, 0) }
 
     menuInflater.inflate(R.menu.activity_main, menu)
-    menu?.findItem(R.id.action_nicklist)?.isVisible = bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer)
-                                                      ?: false
+    menu?.findItem(R.id.action_nicklist)?.isVisible =
+      bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer)
+        ?: false
     menu?.findItem(R.id.action_filter_messages)?.isVisible =
       (bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer) ?: false ||
-       bufferData?.info?.type?.hasFlag(Buffer_Type.QueryBuffer) ?: false)
+        bufferData?.info?.type?.hasFlag(Buffer_Type.QueryBuffer) ?: false)
     menu?.retint(binding.layoutMain.layoutToolbar.toolbar.context)
     menu?.findItem(R.id.action_nicklist)?.icon = NickCountDrawable(
       bufferData?.userCount ?: 0,
       nickCountDrawableSize,
-      nickCountDrawableColor)
+      nickCountDrawableColor
+    )
     return super.onCreateOptionsMenu(menu)
   }
 
   override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
-    android.R.id.home           -> {
+    android.R.id.home -> {
       drawerToggle.onOptionsItemSelected(item)
     }
-    R.id.action_nicklist        -> {
+
+    R.id.action_nicklist -> {
       if (binding.drawerLayout.isDrawerVisible(GravityCompat.END)) {
         binding.drawerLayout.closeDrawer(GravityCompat.END)
       } else {
@@ -989,6 +1086,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       }
       true
     }
+
     R.id.action_filter_messages -> {
       runInBackground {
         chatViewModel.bufferId { buffer ->
@@ -1060,23 +1158,28 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       }
       true
     }
-    R.id.action_core_settings   -> {
+
+    R.id.action_core_settings -> {
       CoreSettingsActivity.launch(this)
       true
     }
+
     R.id.action_client_settings -> {
       ClientSettingsActivity.launch(this)
       true
     }
-    R.id.action_about           -> {
+
+    R.id.action_about -> {
       AboutActivity.launch(this)
       true
     }
-    R.id.action_disconnect      -> {
+
+    R.id.action_disconnect -> {
       disconnect()
       true
     }
-    else                        -> super.onOptionsItemSelected(item)
+
+    else -> super.onOptionsItemSelected(item)
   }
 
   override fun onBackPressed() {
@@ -1159,16 +1262,18 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       accountId: Long? = null,
       forceJoin: Boolean? = null
     ) = context.startActivity(
-      intent(context,
-             sharedText,
-             autoCompleteText,
-             autoCompleteSuffix,
-             channel,
-             nickName,
-             networkId,
-             bufferId,
-             accountId,
-             forceJoin)
+      intent(
+        context,
+        sharedText,
+        autoCompleteText,
+        autoCompleteSuffix,
+        channel,
+        nickName,
+        networkId,
+        bufferId,
+        accountId,
+        forceJoin
+      )
     )
 
     fun intent(
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/PreferenceDialogFragmentCompat.java b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/PreferenceDialogFragmentCompat.java
index 33678e321..aad839cd5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/PreferenceDialogFragmentCompat.java
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/settings/PreferenceDialogFragmentCompat.java
@@ -233,8 +233,7 @@ public abstract class PreferenceDialogFragmentCompat extends DialogFragment impl
       return null;
     }
 
-    LayoutInflater inflater = LayoutInflater.from(context);
-    return inflater.inflate(resId, null);
+    return getLayoutInflater().inflate(resId, null);
   }
 
   /**
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/view/ShadowView.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/view/ShadowView.kt
index 340e32d88..810707145 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/view/ShadowView.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/view/ShadowView.kt
@@ -53,7 +53,6 @@ class ShadowView : View {
     initialize(context, attrs, defStyleAttr, 0)
   }
 
-  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
   constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
     super(context, attrs, defStyleAttr, defStyleRes) {
     initialize(context, attrs, defStyleAttr, defStyleRes)
diff --git a/app/src/main/res/drawable/ic_monochrome.xml b/app/src/main/res/drawable/ic_monochrome.xml
new file mode 100644
index 000000000..397009810
--- /dev/null
+++ b/app/src/main/res/drawable/ic_monochrome.xml
@@ -0,0 +1,26 @@
+<!--
+  Quasseldroid - Quassel client for Android
+
+  Copyright (c) 2023 Janne Mareike Koschinski
+  Copyright (c) 2023 The Quassel Project
+
+  This program is free software: you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 3 as published
+  by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program. If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="48dp"
+  android:height="48dp"
+  android:viewportWidth="108"
+  android:viewportHeight="108">
+  <path android:fillColor="#ffffff" android:pathData="M27 54a 27,27 0 1,0 54,0 h-7 a20,20 0 0,1 -40,0 a20,20 0 0,1 40,0 h7 a 27,27 0 1,0 -54,0 M57.34 62.84 a 5.5,5.5 0 1,0 11,0 a 5.5,5.5 0 1,0 -11,0" />
+</vector>
diff --git a/app/src/main/res/mipmap-v26/ic_launcher.xml b/app/src/main/res/mipmap-v26/ic_launcher.xml
index 102979fec..270925f92 100644
--- a/app/src/main/res/mipmap-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-v26/ic_launcher.xml
@@ -20,4 +20,5 @@
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
   <background android:drawable="@drawable/ic_launcher_background" />
   <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+  <monochrome android:drawable="@drawable/ic_monochrome" />
 </adaptive-icon>
diff --git a/gradle/convention/src/main/kotlin/justjanne.repositories.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.repositories.gradle.kts
deleted file mode 100644
index 01861dc99..000000000
--- a/gradle/convention/src/main/kotlin/justjanne.repositories.gradle.kts
+++ /dev/null
@@ -1,5 +0,0 @@
-repositories {
-  mavenCentral()
-  google()
-  maven(url = "https://jitpack.io")
-}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7924f651a..ec50abdf6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -62,8 +62,10 @@ glide-core = { module = "com.github.bumptech.glide:glide", version.ref = "glide"
 glide-recyclerview = { module = "com.github.bumptech.glide:recyclerview-integration", version.ref = "glide" }
 
 gson = { module = "com.google.code.gson:gson", version = "2.9.0" }
-junit = { module = "junit:junit", version = "4.13.2" }
-kotlinpoet = { module = "com.squareup:kotlinpoet", version = "1.11.0" }
+hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" }
+junit-api = { module = "org.junit.jupiter:junit-jupiter-engine", version = "5.10.0" }
+junit-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version = "5.10.0" }
+kotlinpoet = { module = "com.squareup:kotlinpoet", version = "1.12.0" }
 ksp = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }
 leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version = "2.8.1" }
 
diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts
index 7607e029e..31f417021 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -30,5 +30,7 @@ dependencies {
   implementation(project(":invokerannotations"))
   ksp(project(":invokergenerator"))
 
-  testImplementation(libs.junit)
+  testImplementation(libs.hamcrest)
+  testImplementation(libs.junit.api)
+  testRuntimeOnly(libs.junit.engine)
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/integration/AliasManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/integration/AliasManagerTest.kt
index d0cdd9489..9baad0406 100644
--- a/lib/src/test/java/de/kuschku/libquassel/integration/AliasManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/integration/AliasManagerTest.kt
@@ -26,16 +26,16 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.IAliasManager
 import de.kuschku.libquassel.util.TestSession
 import de.kuschku.libquassel.util.setupTestSession
 import de.kuschku.libquassel.util.with
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
 
 class AliasManagerTest {
   lateinit var session: TestSession
   lateinit var channelBuffer: BufferInfo
   lateinit var queryBuffer: BufferInfo
 
-  @Before
+  @BeforeEach
   fun setUp() {
     session = setupTestSession()
     session.aliasManager.setAliasList(listOf(
diff --git a/lib/src/test/java/de/kuschku/libquassel/integration/BufferViewConfigTest.kt b/lib/src/test/java/de/kuschku/libquassel/integration/BufferViewConfigTest.kt
index 2c46068fe..7e0614465 100644
--- a/lib/src/test/java/de/kuschku/libquassel/integration/BufferViewConfigTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/integration/BufferViewConfigTest.kt
@@ -26,13 +26,13 @@ import de.kuschku.libquassel.protocol.QtType
 import de.kuschku.libquassel.util.TestSession
 import de.kuschku.libquassel.util.setupTestSession
 import de.kuschku.libquassel.util.with
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
 
 class BufferViewConfigTest {
   lateinit var session: TestSession
 
-  @Before
+  @BeforeEach
   fun setUp() {
     session = setupTestSession()
   }
diff --git a/lib/src/test/java/de/kuschku/libquassel/integration/SampleIntegrationTest.kt b/lib/src/test/java/de/kuschku/libquassel/integration/SampleIntegrationTest.kt
index 0f5b8680b..f2f56ac43 100644
--- a/lib/src/test/java/de/kuschku/libquassel/integration/SampleIntegrationTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/integration/SampleIntegrationTest.kt
@@ -20,11 +20,11 @@
 package de.kuschku.libquassel.integration
 
 import de.kuschku.libquassel.protocol.NetworkId
-import de.kuschku.libquassel.protocol.QuasselType
 import de.kuschku.libquassel.protocol.QVariant_
 import de.kuschku.libquassel.protocol.QtType
+import de.kuschku.libquassel.protocol.QuasselType
 import de.kuschku.libquassel.util.withTestSession
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class SampleIntegrationTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/integration/SignedIdNameTests.kt b/lib/src/test/java/de/kuschku/libquassel/integration/SignedIdNameTests.kt
index 21b76ee33..1e662ff34 100644
--- a/lib/src/test/java/de/kuschku/libquassel/integration/SignedIdNameTests.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/integration/SignedIdNameTests.kt
@@ -22,7 +22,7 @@ package de.kuschku.libquassel.integration
 import de.kuschku.libquassel.protocol.IdentityId
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.util.withTestSession
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 /*
  * When implementing SignedIds properly for the first time, we noticed that they were used in
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializerTest.kt
index 743ea0a65..43f663a5b 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class BoolSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
index 803bc62f6..02b6ee53d 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
@@ -25,8 +25,8 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class BufferInfoSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteArraySerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteArraySerializerTest.kt
index 548f340ef..850c2acfb 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteArraySerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteArraySerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertArrayEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertArrayEquals
+import org.junit.jupiter.api.Test
 import java.nio.ByteBuffer
 
 class ByteArraySerializerTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteSerializerTest.kt
index 81850e320..22ba51ce9 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ByteSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 import kotlin.experimental.inv
 
 class ByteSerializerTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/CharSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/CharSerializerTest.kt
index 0f6ebaa36..37cf6d7a0 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/CharSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/CharSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class CharSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializerTest.kt
index d8cd85655..d3cc81c7c 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializerTest.kt
@@ -21,9 +21,13 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.threeten.bp.*
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.threeten.bp.Instant
+import org.threeten.bp.LocalDateTime
+import org.threeten.bp.Month
+import org.threeten.bp.ZoneId
+import org.threeten.bp.ZoneOffset
 
 class DateTimeSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializerTest.kt
index a6963e2d8..af8a8e665 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 import java.net.InetAddress
 
 class HostAddressSerializerTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/IntSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/IntSerializerTest.kt
index e2d3d5d42..6300ba646 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/IntSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/IntSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class IntSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/LongSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/LongSerializerTest.kt
index dd5bf9b59..9b4aa673c 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/LongSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/LongSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class LongSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializerTest.kt
index 8ad3b0bdf..f8364af6b 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializerTest.kt
@@ -19,13 +19,19 @@
 
 package de.kuschku.libquassel.protocol.primitive.serializer
 
-import de.kuschku.libquassel.protocol.*
+import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.protocol.Buffer_Type
+import de.kuschku.libquassel.protocol.Message
+import de.kuschku.libquassel.protocol.Message_Flag
+import de.kuschku.libquassel.protocol.Message_Type
+import de.kuschku.libquassel.protocol.MsgId
+import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 import org.threeten.bp.Instant
 
 class MessageSerializerTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ProtocolInfoSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ProtocolInfoSerializerTest.kt
index ff55d5dc0..b16c6ea8d 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ProtocolInfoSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ProtocolInfoSerializerTest.kt
@@ -24,8 +24,8 @@ import de.kuschku.libquassel.protocol.Protocol_Feature
 import de.kuschku.libquassel.quassel.ProtocolInfo
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class ProtocolInfoSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ShortSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ShortSerializerTest.kt
index f72ed3aad..c5115aecb 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ShortSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/ShortSerializerTest.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 import kotlin.experimental.inv
 
 class ShortSerializerTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt
index 5b07c0bf5..8c52b7c24 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt
@@ -23,9 +23,9 @@ import de.kuschku.libquassel.util.deserialize
 import de.kuschku.libquassel.util.roundTrip
 import org.hamcrest.BaseMatcher
 import org.hamcrest.Description
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertThat
-import org.junit.Test
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class StringSerializerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
index fa9bc86c1..00c37a5da 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/BufferTypeTest.kt
@@ -21,67 +21,69 @@ package de.kuschku.libquassel.quassel
 
 import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.util.flag.hasFlag
-import org.junit.Assert
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertFalse
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
 
 class BufferTypeTest {
   @Test
   fun testHasFlag() {
-    Assert.assertTrue(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.StatusBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.QueryBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.ChannelBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.GroupBuffer))
+    assertTrue(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.StatusBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.QueryBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.ChannelBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.StatusBuffer).hasFlag(Buffer_Type.GroupBuffer))
 
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.StatusBuffer))
-    Assert.assertTrue(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.QueryBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.ChannelBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.GroupBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.StatusBuffer))
+    assertTrue(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.QueryBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.ChannelBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.QueryBuffer).hasFlag(Buffer_Type.GroupBuffer))
 
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.StatusBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.QueryBuffer))
-    Assert.assertTrue(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.ChannelBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.GroupBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.StatusBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.QueryBuffer))
+    assertTrue(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.ChannelBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.ChannelBuffer).hasFlag(Buffer_Type.GroupBuffer))
 
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.StatusBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.QueryBuffer))
-    Assert.assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.ChannelBuffer))
-    Assert.assertTrue(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.GroupBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.StatusBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.QueryBuffer))
+    assertFalse(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.ChannelBuffer))
+    assertTrue(Buffer_Type.of(Buffer_Type.GroupBuffer).hasFlag(Buffer_Type.GroupBuffer))
   }
 
   @Test
   fun testEnabledValues() {
-    Assert.assertEquals(
+    assertEquals(
       Buffer_Type.StatusBuffer,
       Buffer_Type.of(Buffer_Type.StatusBuffer).enabledValues().firstOrNull()
     )
-    Assert.assertEquals(
+    assertEquals(
       setOf(Buffer_Type.StatusBuffer),
       Buffer_Type.of(Buffer_Type.StatusBuffer).enabledValues()
     )
 
-    Assert.assertEquals(
+    assertEquals(
       Buffer_Type.QueryBuffer,
       Buffer_Type.of(Buffer_Type.QueryBuffer).enabledValues().firstOrNull()
     )
-    Assert.assertEquals(
+    assertEquals(
       setOf(Buffer_Type.QueryBuffer),
       Buffer_Type.of(Buffer_Type.QueryBuffer).enabledValues()
     )
 
-    Assert.assertEquals(
+    assertEquals(
       Buffer_Type.ChannelBuffer,
       Buffer_Type.of(Buffer_Type.ChannelBuffer).enabledValues().firstOrNull()
     )
-    Assert.assertEquals(
+    assertEquals(
       setOf(Buffer_Type.ChannelBuffer),
       Buffer_Type.of(Buffer_Type.ChannelBuffer).enabledValues()
     )
 
-    Assert.assertEquals(
+    assertEquals(
       Buffer_Type.GroupBuffer,
       Buffer_Type.of(Buffer_Type.GroupBuffer).enabledValues().firstOrNull()
     )
-    Assert.assertEquals(
+    assertEquals(
       setOf(Buffer_Type.GroupBuffer),
       Buffer_Type.of(Buffer_Type.GroupBuffer).enabledValues()
     )
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
index 3d2008a65..bb164e9d0 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
@@ -22,7 +22,7 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class AliasManagerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferSyncerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferSyncerTest.kt
index 2a64f7c8b..165fcd9d6 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferSyncerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferSyncerTest.kt
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.protocol.MsgId
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class BufferSyncerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
index 94eea57ff..3299d2518 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
@@ -24,8 +24,12 @@ import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.SignalProxy
-import de.kuschku.libquassel.util.*
-import org.junit.Test
+import de.kuschku.libquassel.util.randomBoolean
+import de.kuschku.libquassel.util.randomInt
+import de.kuschku.libquassel.util.randomOf
+import de.kuschku.libquassel.util.randomString
+import de.kuschku.libquassel.util.roundTrip
+import org.junit.jupiter.api.Test
 
 class BufferViewConfigTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewManagerTest.kt
index 258eaf969..3cb6fa9b2 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewManagerTest.kt
@@ -22,7 +22,7 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class BufferViewManagerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
index 84dbbce94..9737bfab1 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
@@ -22,8 +22,12 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.quassel.syncables.interfaces.IHighlightRuleManager
 import de.kuschku.libquassel.session.SignalProxy
-import de.kuschku.libquassel.util.*
-import org.junit.Test
+import de.kuschku.libquassel.util.randomBoolean
+import de.kuschku.libquassel.util.randomInt
+import de.kuschku.libquassel.util.randomOf
+import de.kuschku.libquassel.util.randomString
+import de.kuschku.libquassel.util.roundTrip
+import org.junit.jupiter.api.Test
 
 class HighlightRuleManagerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
index 93da54521..ea5ee6e59 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.randomInt
 import de.kuschku.libquassel.util.randomString
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class IdentityTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
index 1d4e58da4..e29d392cb 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.util.randomBoolean
 import de.kuschku.libquassel.util.randomOf
 import de.kuschku.libquassel.util.randomString
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 
 class IgnoreListManagerTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
index ff981a4fa..a1a3091a9 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
@@ -24,7 +24,7 @@ import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.randomBoolean
 import de.kuschku.libquassel.util.randomInt
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Test
+import org.junit.jupiter.api.Test
 import kotlin.math.abs
 
 class NetworkConfigTest {
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
index c06367443..f0be3e52e 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
@@ -24,8 +24,16 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.SignalProxy
-import de.kuschku.libquassel.util.*
-import org.junit.Test
+import de.kuschku.libquassel.util.randomBoolean
+import de.kuschku.libquassel.util.randomCharset
+import de.kuschku.libquassel.util.randomInstant
+import de.kuschku.libquassel.util.randomInt
+import de.kuschku.libquassel.util.randomOf
+import de.kuschku.libquassel.util.randomString
+import de.kuschku.libquassel.util.randomUInt
+import de.kuschku.libquassel.util.randomUShort
+import de.kuschku.libquassel.util.roundTrip
+import org.junit.jupiter.api.Test
 
 class NetworkTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetworkInfoTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetworkInfoTest.kt
index 517f82396..d2727cbde 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetworkInfoTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetworkInfoTest.kt
@@ -23,8 +23,8 @@ import de.kuschku.libquassel.protocol.IdentityId
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_PLAINTEXT
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class INetworkInfoTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/ExpressionMatchTest.kt b/lib/src/test/java/de/kuschku/libquassel/util/ExpressionMatchTest.kt
index 86aba750f..e422365a9 100644
--- a/lib/src/test/java/de/kuschku/libquassel/util/ExpressionMatchTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/util/ExpressionMatchTest.kt
@@ -19,8 +19,10 @@
 
 package de.kuschku.libquassel.util
 
-import org.junit.Assert.*
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertFalse
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
 
 class ExpressionMatchTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt b/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt
index aec1e47e8..31ed64d7e 100644
--- a/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt
@@ -56,7 +56,7 @@ import de.kuschku.libquassel.session.ProtocolHandler
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import io.reactivex.subjects.PublishSubject
-import org.junit.Assert.assertTrue
+import org.junit.jupiter.api.Assertions.assertTrue
 import javax.net.ssl.SSLSession
 
 class TestSession : ProtocolHandler({ throw it }), ISession {
@@ -79,35 +79,35 @@ class TestSession : ProtocolHandler({ throw it }), ISession {
         it.className == target.className
       }
       assertTrue(
-        "SYNC No calls were made on objects of type ${target.className}",
-        matchingTargetTypes.isNotEmpty()
+        matchingTargetTypes.isNotEmpty(),
+        "SYNC No calls were made on objects of type ${target.className}"
       )
       val matchingTargets = matchingTargetTypes.filter {
         it.objectName == target.objectName
       }
       assertTrue(
+        matchingTargets.isNotEmpty(),
         if (matchingTargetTypes.isNotEmpty()) {
           "SYNC No calls were made on ${target.className}:${target.objectName}, instead only on:\n  ${matchingTargetTypes.map { "${it.className}:${it.objectName}" }.joinToString(
             "\n  ")}"
         } else {
           "SYNC No calls were made on ${target.className}:${target.objectName}"
-        },
-        matchingTargets.isNotEmpty()
+        }
       )
 
       val matchingNames = matchingTargets.filter {
         it.slotName == slotName
       }
       assertTrue(
-        "SYNC ${target.className}:${target.objectName}:$slotName() was never called",
-        matchingNames.isNotEmpty()
+        matchingNames.isNotEmpty(),
+        "SYNC ${target.className}:${target.objectName}:$slotName() was never called"
       )
       if (!params.isNullOrEmpty()) {
         val calledParams = matchingNames.map(SignalProxyMessage.SyncMessage::params)
         assertTrue(
+          calledParams.contains(params),
           "SYNC ${target.className}:${target.objectName}:$slotName was called with the wrong parameters:\nExpected:\n  $params\nActual:\n  ${calledParams.joinToString(
-            "\n  ")}",
-          calledParams.contains(params)
+            "\n  ")}"
         )
       }
     }
@@ -118,15 +118,15 @@ class TestSession : ProtocolHandler({ throw it }), ISession {
         it.slotName == slotName
       }
       assertTrue(
-        "RPC $slotName() was not called",
-        matchingNames.isNotEmpty()
+        matchingNames.isNotEmpty(),
+        "RPC $slotName() was not called"
       )
       if (!params.isNullOrEmpty()) {
         val calledParams = matchingNames.map(SignalProxyMessage.RpcCall::params)
         assertTrue(
+          calledParams.contains(params),
           "RPC $slotName was called with the wrong parameters:\nExpected:\n  $params\nActual:\n  ${calledParams.joinToString(
-            "\n  ")}",
-          calledParams.contains(params)
+            "\n  ")}"
         )
       }
     }
@@ -136,16 +136,16 @@ class TestSession : ProtocolHandler({ throw it }), ISession {
         it.className == className
       }
       assertTrue(
-        "InitRequest No data was requested for objects of type $className",
-        matchingType.isNotEmpty()
+        matchingType.isNotEmpty(),
+        "InitRequest No data was requested for objects of type $className"
       )
       val matchingCalls = matchingType.filter {
         it.objectName == objectName
       }
       assertTrue(
+        matchingCalls.isNotEmpty(),
         "InitRequest No data was requested for object $className:$objectName, instead only for:\n  ${matchingType.map { "${it.className}:${it.objectName}" }.joinToString(
-          "\n  ")}",
-        matchingCalls.isNotEmpty()
+          "\n  ")}"
       )
     }
   }
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt b/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt
index a49ccbd89..04d69d2cf 100644
--- a/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt
@@ -19,8 +19,8 @@
 
 package de.kuschku.libquassel.util.irc
 
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class HostmaskHelperTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/nio/WrappedChannelTest.kt b/lib/src/test/java/de/kuschku/libquassel/util/nio/WrappedChannelTest.kt
index ff5bbc085..7cc4b940b 100644
--- a/lib/src/test/java/de/kuschku/libquassel/util/nio/WrappedChannelTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/util/nio/WrappedChannelTest.kt
@@ -20,8 +20,8 @@
 package de.kuschku.libquassel.util.nio
 
 import de.kuschku.libquassel.util.nio.WrappedChannel.Companion.selectBestTlsVersion
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class WrappedChannelTest {
   @Test
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/rxjava/ReusableUnicastSubjectTest.kt b/lib/src/test/java/de/kuschku/libquassel/util/rxjava/ReusableUnicastSubjectTest.kt
index 7310ea8de..01d15162c 100644
--- a/lib/src/test/java/de/kuschku/libquassel/util/rxjava/ReusableUnicastSubjectTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/util/rxjava/ReusableUnicastSubjectTest.kt
@@ -19,8 +19,8 @@
 
 package de.kuschku.libquassel.util.rxjava
 
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class ReusableUnicastSubjectTest {
   @Test
diff --git a/lint.xml b/lint.xml
index eab67bd5e..fe9afed56 100644
--- a/lint.xml
+++ b/lint.xml
@@ -33,7 +33,8 @@
   <issue id="Overdraw" severity="ignore" />
 
   <!-- Can’t request a translation without a release, can’t release without translation -->
-  <issue id="MissingTranslation" severity="informational" />
+  <issue id="MissingTranslation" severity="ignore" />
+  <issue id="MissingQuantity" severity="ignore" />
   <!-- Because we don’t use app bundles and never will use them -->
   <issue id="AppBundleLocaleChanges" severity="informational" />
   <!-- Because this tries to apply english orthography to other locales -->
diff --git a/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt b/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt
index 01f5e2ba7..9842e4217 100644
--- a/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt
+++ b/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt
@@ -19,6 +19,7 @@
 
 package de.kuschku.malheur.collectors
 
+import android.annotation.SuppressLint
 import android.app.Application
 import android.content.res.Configuration
 import android.util.SparseArray
@@ -86,6 +87,7 @@ class ConfigurationCollector(private val application: Application) :
     }
   }
 
+  @SuppressLint("PrivateApi")
   override fun collect(context: CrashContext,
                        config: Boolean) = configurationFields.mapNotNull { info ->
     val field: Field? = Configuration::class.java.getDeclaredField(info.fieldName)
diff --git a/viewmodel/build.gradle.kts b/viewmodel/build.gradle.kts
index 112321477..1fb805a14 100644
--- a/viewmodel/build.gradle.kts
+++ b/viewmodel/build.gradle.kts
@@ -47,5 +47,6 @@ dependencies {
     exclude(group = "org.threeten", module = "threetenbp")
   }
 
-  testImplementation(libs.junit)
+  testImplementation(libs.junit.api)
+  testRuntimeOnly(libs.junit.engine)
 }
diff --git a/viewmodel/src/test/java/de/kuschku/quasseldroid/viewmodel/ChatViewModelTest.kt b/viewmodel/src/test/java/de/kuschku/quasseldroid/viewmodel/ChatViewModelTest.kt
index 063d14a1d..2a6112aff 100644
--- a/viewmodel/src/test/java/de/kuschku/quasseldroid/viewmodel/ChatViewModelTest.kt
+++ b/viewmodel/src/test/java/de/kuschku/quasseldroid/viewmodel/ChatViewModelTest.kt
@@ -20,8 +20,8 @@
 package de.kuschku.quasseldroid.viewmodel
 
 import de.kuschku.quasseldroid.viewmodel.ChatViewModel.Companion.recentMessagesChangeInternal
-import org.junit.Assert.assertEquals
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
 
 class ChatViewModelTest {
   @Test
-- 
GitLab