diff --git a/app/build.gradle b/app/build.gradle
index 7fa2d15fd5..85a3206e6a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,7 +5,7 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.4.2'
+        classpath "com.android.tools.build:gradle:$gradlePluginVersion"
         classpath files('libs/gradle-witness.jar')
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
         classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
diff --git a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
index a99b40f36f..d5db6ae041 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
@@ -14,6 +14,7 @@ import androidx.annotation.LayoutRes
 import androidx.annotation.StringRes
 import androidx.annotation.StyleRes
 import androidx.appcompat.app.AlertDialog
+import androidx.core.text.HtmlCompat
 import androidx.core.view.setMargins
 import androidx.core.view.setPadding
 import androidx.core.view.updateMargins
@@ -21,7 +22,6 @@ import androidx.fragment.app.Fragment
 import network.loki.messenger.R
 import org.thoughtcrime.securesms.util.toPx
 
-
 @DslMarker
 @Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
 annotation class DialogDsl
@@ -64,7 +64,6 @@ class SessionDialogBuilder(val context: Context) {
         }
     }
 
-
     private fun text(text: CharSequence?, @StyleRes style: Int, modify: TextView.() -> Unit) {
         text ?: return
         TextView(context, null, 0, style)
@@ -75,6 +74,8 @@ class SessionDialogBuilder(val context: Context) {
             }.let(topView::addView)
     }
 
+    fun htmlText(@StringRes id: Int, @StyleRes style: Int = 0, modify: TextView.() -> Unit = {}) { text(context.resources.getText(id)) }
+
     fun view(view: View) = contentView.addView(view)
 
     fun view(@LayoutRes layout: Int): View = LayoutInflater.from(context).inflate(layout, contentView)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LoadingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LoadingActivity.kt
index e68fcb541a..523bc17888 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LoadingActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LoadingActivity.kt
@@ -18,9 +18,11 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.res.stringResource
 import androidx.lifecycle.lifecycleScope
 import dagger.hilt.android.AndroidEntryPoint
 import kotlinx.coroutines.launch
+import network.loki.messenger.R
 import org.session.libsession.utilities.TextSecurePreferences
 import org.thoughtcrime.securesms.BaseActionBarActivity
 import org.thoughtcrime.securesms.dependencies.ConfigFactory
@@ -99,8 +101,8 @@ class LoadingActivity: BaseActionBarActivity() {
             Column {
                 Spacer(modifier = Modifier.weight(1f))
                 ProgressArc(animatable.value, modifier = Modifier.align(Alignment.CenterHorizontally))
-                Text("One moment please..", modifier = Modifier.align(Alignment.CenterHorizontally), style = MaterialTheme.typography.h6)
-                Text("Loading your account", modifier = Modifier.align(Alignment.CenterHorizontally))
+                Text(stringResource(R.string.waitOneMoment), modifier = Modifier.align(Alignment.CenterHorizontally), style = MaterialTheme.typography.h6)
+                Text(stringResource(R.string.loadAccountProgressMessage), modifier = Modifier.align(Alignment.CenterHorizontally))
                 Spacer(modifier = Modifier.weight(2f))
             }
         }
diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt
index 42fc83f05e..00b6e6c3e0 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt
@@ -61,16 +61,16 @@ class MessageNotificationsActivity : BaseActionBarActivity() {
         TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
 
         ComposeView(this)
-            .apply { setContent { MessageNotifications() } }
+            .apply { setContent { MessageNotificationsScreen() } }
             .let(::setContentView)
     }
 
     @Composable
-    private fun MessageNotifications() {
+    private fun MessageNotificationsScreen() {
         val state by viewModel.stateFlow.collectAsState()
 
         AppTheme {
-            MessageNotifications(state, viewModel::setEnabled, ::register)
+            MessageNotificationsScreen(state, viewModel::setEnabled, ::register)
         }
     }
 
@@ -87,25 +87,25 @@ class MessageNotificationsActivity : BaseActionBarActivity() {
 
 @Preview
 @Composable
-fun MessageNotificationsPreview(
+fun MessageNotificationsScreenPreview(
     @PreviewParameter(ThemeResPreviewParameterProvider::class) themeResId: Int
 ) {
     PreviewTheme(themeResId) {
-        MessageNotifications()
+        MessageNotificationsScreen()
     }
 }
 
 @Composable
-fun MessageNotifications(
+fun MessageNotificationsScreen(
     state: MessageNotificationsState = MessageNotificationsState(),
     setEnabled: (Boolean) -> Unit = {},
     onContinue: () -> Unit = {}
 ) {
     Column(Modifier.padding(horizontal = 32.dp)) {
         Spacer(Modifier.weight(1f))
-        Text("Message notifications", style = MaterialTheme.typography.h4)
+        Text(stringResource(R.string.notificationsMessage), style = MaterialTheme.typography.h4)
         Spacer(Modifier.height(16.dp))
-        Text("There are two ways Session can notify you of new messages.")
+        Text(stringResource(R.string.onboardingMessageNotificationExplaination))
         Spacer(Modifier.height(16.dp))
         NotificationRadioButton(
             R.string.activity_pn_mode_fast_mode,
@@ -125,8 +125,8 @@ fun MessageNotifications(
         OutlineButton(
             stringResource(R.string.continue_2),
             modifier = Modifier
-                .align(Alignment.CenterHorizontally)
-                .width(262.dp),
+                    .align(Alignment.CenterHorizontally)
+                    .width(262.dp),
             onClick = onContinue
         )
         Spacer(modifier = Modifier.height(12.dp))
diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt
index a95cde5261..4c70cfe455 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt
@@ -7,6 +7,8 @@ import android.os.Bundle
 import androidx.activity.viewModels
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.Crossfade
+import androidx.compose.animation.core.animateValue
+import androidx.compose.animation.core.rememberInfiniteTransition
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
@@ -27,9 +29,11 @@ import androidx.compose.material.Icon
 import androidx.compose.material.MaterialTheme
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.ColorFilter
@@ -41,6 +45,9 @@ import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 import network.loki.messenger.R
 import org.thoughtcrime.securesms.BaseActionBarActivity
 import org.thoughtcrime.securesms.showSessionDialog
@@ -55,6 +62,7 @@ import org.thoughtcrime.securesms.ui.classicDarkColors
 import org.thoughtcrime.securesms.ui.colorDestructive
 import org.thoughtcrime.securesms.ui.h8
 import org.thoughtcrime.securesms.ui.small
+import kotlin.time.Duration.Companion.seconds
 
 class RecoveryPasswordActivity : BaseActionBarActivity() {
 
@@ -73,20 +81,18 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
 
     private fun onHide() {
         showSessionDialog {
-            title("Hide Recovery Password Permanently")
-            text("Without your recovery password, you cannot load your account on new devices.\n" +
-                "\n" +
-                "We strongly recommend you save your recovery password in a safe and secure place before continuing.")
+            title(R.string.recoveryPasswordHidePermanently)
+            htmlText(R.string.recoveryPasswordHidePermanentlyDescription1)
             destructiveButton(R.string.continue_2) { onHideConfirm() }
-            button(R.string.cancel) {}
+            cancelButton()
         }
     }
 
     private fun onHideConfirm() {
         showSessionDialog {
-            title("Hide Recovery Password Permanently")
-            text("Are you sure you want to permanently hide your recovery password on this device? This cannot be undone.")
-            button(R.string.cancel) {}
+            title(R.string.recoveryPasswordHidePermanently)
+            text(R.string.recoveryPasswordHidePermanentlyDescription2)
+            cancelButton()
             destructiveButton(R.string.yes) {
                 viewModel.permanentlyHidePassword()
                 finish()
@@ -131,31 +137,27 @@ fun RecoveryPasswordCell(seed: String = "", qrBitmap: Bitmap? = null, copySeed:(
         mutableStateOf(false)
     }
 
-    val copied = remember {
-        mutableStateOf(false)
-    }
-
     CellWithPaddingAndMargin {
         Column {
             Row {
-                Text("Recovery Password")
+                Text(stringResource(R.string.sessionRecoveryPassword))
                 Spacer(Modifier.width(8.dp))
                 SessionShieldIcon()
             }
 
-            Text("Use your recovery password to load your account on new devices.\n\nYour account cannot be recovered without your recovery password. Make sure it's stored somewhere safe and secure — and don't share it with anyone.")
+            Text(stringResource(R.string.recoveryPasswordDescription))
 
             AnimatedVisibility(!showQr.value) {
                 Text(
                     seed,
                     modifier = Modifier
-                            .padding(vertical = 24.dp)
-                            .border(
-                                    width = 1.dp,
-                                    color = classicDarkColors[3],
-                                    shape = RoundedCornerShape(11.dp)
-                            )
-                            .padding(24.dp),
+                        .padding(vertical = 24.dp)
+                        .border(
+                            width = 1.dp,
+                            color = classicDarkColors[3],
+                            shape = RoundedCornerShape(11.dp)
+                        )
+                        .padding(24.dp),
                     style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace),
                     color = LocalExtraColors.current.prominentButtonColor,
                 )
@@ -166,8 +168,8 @@ fun RecoveryPasswordCell(seed: String = "", qrBitmap: Bitmap? = null, copySeed:(
                     backgroundColor = LocalExtraColors.current.lightCell,
                     elevation = 0.dp,
                     modifier = Modifier
-                            .align(Alignment.CenterHorizontally)
-                            .padding(vertical = 24.dp)
+                        .align(Alignment.CenterHorizontally)
+                        .padding(vertical = 24.dp)
                 ) {
                     Box {
                         qrBitmap?.let {
@@ -183,11 +185,11 @@ fun RecoveryPasswordCell(seed: String = "", qrBitmap: Bitmap? = null, copySeed:(
                             contentDescription = "",
                             tint = LocalExtraColors.current.onLightCell,
                             modifier = Modifier
-                                    .align(Alignment.Center)
-                                    .width(46.dp)
-                                    .height(56.dp)
-                                    .background(color = LocalExtraColors.current.lightCell)
-                                    .padding(horizontal = 3.dp, vertical = 1.dp)
+                                .align(Alignment.Center)
+                                .width(46.dp)
+                                .height(56.dp)
+                                .background(color = LocalExtraColors.current.lightCell)
+                                .padding(horizontal = 3.dp, vertical = 1.dp)
                         )
                     }
                 }
@@ -195,16 +197,36 @@ fun RecoveryPasswordCell(seed: String = "", qrBitmap: Bitmap? = null, copySeed:(
 
             AnimatedVisibility(!showQr.value) {
                 Row(horizontalArrangement = Arrangement.spacedBy(32.dp)) {
-                    Crossfade(targetState = if (copied.value) R.string.copied else R.string.copy, modifier = Modifier.weight(1f), label = "Copy to Copied CrossFade") {
-                        OutlineButton(text = stringResource(it), modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colors.onPrimary) { copySeed(); copied.value = true }
+                    val scope = rememberCoroutineScope()
+                    val revertCopiedTextJob = remember { mutableStateOf<Job?>(null) }
+                    val copied = remember { mutableStateOf(false) }
+                    OutlineButton(
+                        modifier = Modifier.weight(1f),
+                        color = MaterialTheme.colors.onPrimary,
+                        onClick = {
+                            copySeed()
+                            revertCopiedTextJob.value?.cancel()
+                            revertCopiedTextJob.value = scope.launch {
+                                copied.value = true
+                                delay(2.seconds)
+                                copied.value = false
+                            }
+                        }
+                    ) {
+                        AnimatedVisibility(!copied.value) {
+                            Text(stringResource(R.string.copy))
+                        }
+                        AnimatedVisibility(copied.value) {
+                            Text(stringResource(R.string.copied))
+                        }
                     }
-                    OutlineButton(text = "View QR", modifier = Modifier.weight(1f), color = MaterialTheme.colors.onPrimary) { showQr.toggle() }
+                    OutlineButton(text = stringResource(R.string.qrView), modifier = Modifier.weight(1f), color = MaterialTheme.colors.onPrimary) { showQr.toggle() }
                 }
             }
 
             AnimatedVisibility(showQr.value, modifier = Modifier.align(Alignment.CenterHorizontally)) {
                 OutlineButton(
-                    text = "View Password",
+                    text = stringResource(R.string.recoveryPasswordView),
                     color = MaterialTheme.colors.onPrimary,
                     modifier = Modifier.align(Alignment.CenterHorizontally)
                 ) { showQr.toggle() }
@@ -220,11 +242,11 @@ fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
     CellWithPaddingAndMargin {
         Row {
             Column(Modifier.weight(1f)) {
-                Text(text = "Hide Recovery Password", style = MaterialTheme.typography.h8)
-                Text(text = "Permanently hide your recovery password on this device.")
+                Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPassword), style = MaterialTheme.typography.h8)
+                Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPasswordDescription))
             }
             OutlineButton(
-                "Hide",
+                stringResource(R.string.hide),
                 modifier = Modifier.align(Alignment.CenterVertically),
                 color = colorDestructive
             ) { onHide() }
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt
index 023353477a..262b2e6e59 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt
@@ -84,6 +84,27 @@ fun OutlineButton(
     }
 }
 
+@Composable
+fun OutlineButton(
+    modifier: Modifier = Modifier,
+    color: Color = LocalExtraColors.current.prominentButtonColor,
+    onClick: () -> Unit = {},
+    content: @Composable () -> Unit = {}
+) {
+    OutlinedButton(
+        modifier = modifier,
+        onClick = onClick,
+        border = BorderStroke(1.dp, color),
+        shape = RoundedCornerShape(50), // = 50% percent
+        colors = ButtonDefaults.outlinedButtonColors(
+            contentColor = color,
+            backgroundColor = Color.Unspecified
+        )
+    ) {
+        content()
+    }
+}
+
 @Composable
 fun FilledButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) {
     OutlinedButton(
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5b4a7edeed..4d476d02af 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1081,4 +1081,17 @@
     <string name="activity_link_load_account">Load Account</string>
     <string name="activity_link_camera_permission_permanently_denied_configure_in_settings">Camera Permission permanently denied. Configure in settings.</string>
     <string name="activity_link_enter_your_recovery_password_to_load_your_account_if_you_haven_t_saved_it_you_can_find_it_in_your_app_settings">Enter your recovery password to load your account. If you haven\'t saved it, you can find it in your app settings.</string>
+    <string name="waitOneMoment">One moment please..</string>
+    <string name="loadAccountProgressMessage">Loading your account</string>
+    <string name="notificationsMessage">Message notifications</string>
+    <string name="onboardingMessageNotificationExplaination">There are two ways Session can notify you of new messages.</string>
+    <string name="recoveryPasswordHidePermanently">Hide Recovery Password Permanently</string>
+    <string name="recoveryPasswordHidePermanentlyDescription1"><![CDATA[Without your recovery password, you cannot load your account on new devices. <br /><br />We strongly recommend you save your recovery password in a safe and secure place before continuing.]]></string>
+    <string name="recoveryPasswordHidePermanentlyDescription2">Are you sure you want to permanently hide your recovery password on this device? This cannot be undone.</string>
+    <string name="recoveryPasswordDescription">Use your recovery password to load your account on new devices. Your account cannot be recovered without your recovery password. Make sure it\'s stored somewhere safe and secure — and don\'t share it with anyone.</string>
+    <string name="hide">Hide</string>
+    <string name="recoveryPasswordHideRecoveryPassword">Hide Recovery Password</string>
+    <string name="qrView">View QR</string>
+    <string name="recoveryPasswordView">View Password</string>
+    <string name="recoveryPasswordHideRecoveryPasswordDescription">Permanently hide your recovery password on this device.</string>
 </resources>
diff --git a/gradle.properties b/gradle.properties
index e6dd30852e..66ea0fcba8 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -16,7 +16,7 @@ android.enableJetifier=true
 org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
 org.gradle.unsafe.configuration-cache=true
 
-gradlePluginVersion=7.3.1
+gradlePluginVersion=7.4.2
 googleServicesVersion=4.3.12
 kotlinVersion=1.8.21
 android.useAndroidX=true