diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1af49c35dd..282d8854f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -257,6 +257,307 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= 26) {
+ clickPref(
+ title = DSLSettingsText.from(R.string.preferences__app_icon),
+ onClick = {
+ Navigation.findNavController(requireView()).safeNavigate(R.id.action_appearanceSettings_to_appIconActivity)
+ }
+ )
+ }
+
radioListPref(
title = DSLSettingsText.from(R.string.preferences_chats__message_text_size),
listItems = messageFontSizeLabels,
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconSelectionFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconSelectionFragment.kt
new file mode 100644
index 0000000000..71e67001e4
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconSelectionFragment.kt
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.components.settings.app.appearance.appicon
+
+import android.content.Context
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.text.ClickableText
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.navigation.fragment.findNavController
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toImmutableList
+import org.signal.core.ui.Scaffolds
+import org.signal.core.util.logging.Log
+import org.thoughtcrime.securesms.R
+import org.thoughtcrime.securesms.components.settings.app.appearance.appicon.util.AppIconPreset
+import org.thoughtcrime.securesms.components.settings.app.appearance.appicon.util.AppIconUtility
+import org.thoughtcrime.securesms.compose.ComposeFragment
+import org.thoughtcrime.securesms.util.navigation.safeNavigate
+
+class AppIconSelectionFragment : ComposeFragment() {
+ private lateinit var appIconUtility: AppIconUtility
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ appIconUtility = AppIconUtility(context)
+ }
+
+ @Composable
+ override fun FragmentContent() {
+ Scaffolds.Settings(
+ title = stringResource(id = R.string.preferences__app_icon),
+ onNavigationClick = {
+ findNavController().popBackStack()
+ },
+ navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24),
+ navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
+ ) { contentPadding: PaddingValues ->
+ IconSelectionScreen(appIconUtility.currentAppIcon, ::updateAppIcon, ::openLearnMore, Modifier.padding(contentPadding))
+ }
+ }
+
+ private fun updateAppIcon(preset: AppIconPreset) {
+ if (!appIconUtility.isCurrentlySelected(preset)) {
+ appIconUtility.setNewAppIcon(preset)
+ }
+ }
+
+ private fun openLearnMore() {
+ findNavController().safeNavigate(R.id.action_appIconSelectionFragment_to_appIconTutorialFragment)
+ }
+
+ /**
+ * Screen allowing the user to view all the possible icon and select a new one to use.
+ */
+ @Composable
+ fun IconSelectionScreen(activeIcon: AppIconPreset, onItemConfirmed: (AppIconPreset) -> Unit, onWarningClick: () -> Unit, modifier: Modifier = Modifier) {
+ var showDialog: Boolean by remember { mutableStateOf(false) }
+ var pendingIcon: AppIconPreset by remember {
+ mutableStateOf(activeIcon)
+ }
+
+ if (showDialog) {
+ ChangeIconDialog(
+ pendingIcon = pendingIcon,
+ onConfirm = {
+ onItemConfirmed(pendingIcon)
+ showDialog = false
+ },
+ onDismiss = {
+ pendingIcon = activeIcon
+ showDialog = false
+ }
+ )
+ }
+
+ Column(modifier = modifier.verticalScroll(rememberScrollState())) {
+ Spacer(modifier = Modifier.size(12.dp))
+ CaveatWarning(
+ onClick = onWarningClick,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ )
+ Spacer(modifier = Modifier.size(12.dp))
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 18.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ enumValues().toList().chunked(COLUMN_COUNT).map { it.toImmutableList() }.forEach { items ->
+ IconRow(
+ presets = items,
+ isSelected = { it == pendingIcon },
+ onItemClick = {
+ pendingIcon = it
+ showDialog = true
+ }
+ )
+ }
+ }
+ }
+ }
+
+ @Composable
+ fun ChangeIconDialog(pendingIcon: AppIconPreset, onConfirm: () -> Unit, onDismiss: () -> Unit, modifier: Modifier = Modifier) {
+ AlertDialog(
+ modifier = modifier,
+ onDismissRequest = onDismiss,
+ confirmButton = {
+ TextButton(
+ onClick = onConfirm
+ ) {
+ Text(text = stringResource(id = R.string.preferences__app_icon_dialog_ok))
+ }
+ },
+ dismissButton = {
+ TextButton(
+ onClick = onDismiss
+ ) {
+ Text(text = stringResource(id = R.string.preferences__app_icon_dialog_cancel))
+ }
+ },
+ icon = {
+ AppIcon(preset = pendingIcon, isSelected = false, onClick = {})
+ },
+ title = {
+ Text(
+ text = stringResource(id = R.string.preferences__app_icon_dialog_title, stringResource(id = pendingIcon.labelResId)),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.headlineSmall
+ )
+ },
+ text = {
+ Text(
+ text = stringResource(id = R.string.preferences__app_icon_dialog_description),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.bodyMedium
+ )
+ }
+ )
+ }
+
+ /**
+ * Composable rendering the one row of icons that the user may choose from.
+ */
+ @Composable
+ fun IconRow(presets: ImmutableList, isSelected: (AppIconPreset) -> Boolean, onItemClick: (AppIconPreset) -> Unit, modifier: Modifier = Modifier) {
+ Row(modifier = modifier.fillMaxWidth()) {
+ presets.forEach { preset ->
+ val currentlySelected = isSelected(preset)
+ IconGridElement(
+ preset = preset,
+ isSelected = currentlySelected,
+ onClickHandler = {
+ if (!currentlySelected) {
+ onItemClick(preset)
+ }
+ },
+ modifier = Modifier
+ .padding(vertical = 18.dp)
+ .weight(1f)
+ )
+ }
+ }
+ }
+
+ /**
+ * Composable rendering an individual icon inside that grid, including the black border of the selected icon.
+ */
+ @Composable
+ fun IconGridElement(preset: AppIconPreset, isSelected: Boolean, onClickHandler: () -> Unit, modifier: Modifier = Modifier) {
+ Column(
+ modifier = modifier,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ val boxModifier = Modifier.size(64.dp)
+ Box(
+ modifier = if (isSelected) boxModifier.border(3.dp, MaterialTheme.colorScheme.onBackground, CircleShape) else boxModifier
+ ) {
+ AppIcon(preset = preset, isSelected = isSelected, onClickHandler, modifier = Modifier.align(Alignment.Center))
+ }
+ Spacer(modifier = Modifier.size(8.dp))
+ Text(
+ text = stringResource(id = preset.labelResId),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ }
+
+ /**
+ * Composable rendering the multiple layers of an adaptive icon onto one flattened rasterized Canvas.
+ */
+ @Composable
+ fun AppIcon(preset: AppIconPreset, isSelected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
+ val bitmapSize: Dp = if (isSelected) 48.dp else 64.dp
+ val imageModifier = modifier
+ .size(bitmapSize)
+ .graphicsLayer(
+ shape = CircleShape,
+ shadowElevation = if (isSelected) 4f else 8f,
+ clip = true
+ )
+ .clickable(onClick = onClick)
+ Image(
+ painterResource(id = preset.iconPreviewResId),
+ contentDescription = stringResource(id = preset.labelResId),
+ modifier = imageModifier
+ )
+ }
+
+ /**
+ * A clickable "learn more" block of text.
+ */
+ @Composable
+ fun CaveatWarning(onClick: () -> Unit, modifier: Modifier = Modifier) {
+ val learnMoreString = stringResource(R.string.preferences__app_icon_learn_more)
+ val completeString = stringResource(R.string.preferences__app_icon_warning_learn_more)
+ val learnMoreStartIndex = completeString.indexOf(learnMoreString).coerceAtLeast(0)
+ val learnMoreEndIndex = learnMoreStartIndex + learnMoreString.length
+ val doesStringEndWithLearnMore = learnMoreEndIndex >= completeString.lastIndex
+ val annotatedText = buildAnnotatedString {
+ withStyle(
+ style = SpanStyle(
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ ) {
+ append(completeString.substring(0, learnMoreStartIndex))
+ }
+ pushStringAnnotation(
+ tag = URL_TAG,
+ annotation = LEARN_MORE_TAG
+ )
+ withStyle(
+ style = SpanStyle(
+ color = MaterialTheme.colorScheme.primary
+ )
+ ) {
+ append(learnMoreString)
+ }
+ pop()
+ if (!doesStringEndWithLearnMore) {
+ append(completeString.substring(learnMoreEndIndex, completeString.lastIndex))
+ }
+ }
+ ClickableText(
+ text = annotatedText,
+ onClick = { _ ->
+ onClick()
+ },
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = modifier
+ )
+ }
+
+ @Preview
+ @Composable
+ private fun MainScreenPreview() {
+ IconSelectionScreen(AppIconPreset.DEFAULT, onItemConfirmed = {}, onWarningClick = {})
+ }
+
+ companion object {
+ val TAG = Log.tag(AppIconSelectionFragment::class.java)
+
+ private const val LEARN_MORE_TAG = "learn_more"
+ private const val URL_TAG = "URL"
+ private const val COLUMN_COUNT = 4
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconTutorialFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconTutorialFragment.kt
new file mode 100644
index 0000000000..28e4b8686c
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/AppIconTutorialFragment.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.components.settings.app.appearance.appicon
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.navigation.fragment.findNavController
+import org.signal.core.ui.Scaffolds
+import org.signal.core.util.logging.Log
+import org.thoughtcrime.securesms.R
+import org.thoughtcrime.securesms.compose.ComposeFragment
+
+class AppIconTutorialFragment : ComposeFragment() {
+
+ @Composable
+ override fun FragmentContent() {
+ Scaffolds.Settings(
+ title = "",
+ onNavigationClick = {
+ findNavController().popBackStack()
+ },
+ navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24),
+ navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
+ ) { contentPadding: PaddingValues ->
+ TutorialScreen(Modifier.padding(contentPadding))
+ }
+ }
+
+ @Composable
+ fun TutorialScreen(modifier: Modifier = Modifier) {
+ Box(modifier = modifier) {
+ Column(
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(Alignment.Center)
+ .verticalScroll(rememberScrollState()),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ val borderShape = RoundedCornerShape(12.dp)
+
+ Text(
+ text = stringResource(R.string.preferences__app_icon_warning),
+ style = MaterialTheme.typography.bodyLarge,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(vertical = 20.dp)
+ )
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(borderShape)
+ .border(1.dp, MaterialTheme.colorScheme.outline, shape = borderShape)
+ ) {
+ Image(
+ painter = painterResource(R.drawable.app_icon_tutorial_apps_homescreen),
+ contentDescription = stringResource(R.string.preferences__graphic_illustrating_where_the_replacement_app_icon_will_be_visible),
+ contentScale = ContentScale.FillWidth,
+ modifier = Modifier
+ .widthIn(max = 328.dp)
+ )
+ }
+ Text(
+ text = stringResource(id = R.string.preferences__app_icon_notification_warning),
+ style = MaterialTheme.typography.bodyLarge,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(vertical = 20.dp)
+ )
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(borderShape)
+ .border(1.dp, MaterialTheme.colorScheme.outline, shape = borderShape)
+ ) {
+ Image(
+ painter = painterResource(R.drawable.app_icon_tutorial_notification),
+ contentDescription = stringResource(R.string.preferences__graphic_illustrating_where_the_replacement_app_icon_will_be_visible),
+ contentScale = ContentScale.FillWidth,
+ modifier = Modifier
+ .widthIn(max = 328.dp)
+ )
+ }
+ }
+ }
+ }
+
+ @Preview
+ @Composable
+ private fun TutorialScreenPreview() {
+ TutorialScreen()
+ }
+
+ companion object {
+ val TAG = Log.tag(AppIconTutorialFragment::class.java)
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconPreset.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconPreset.kt
new file mode 100644
index 0000000000..145455e2cc
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconPreset.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.components.settings.app.appearance.appicon.util
+
+import android.content.ComponentName
+import android.content.Context
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import org.thoughtcrime.securesms.R
+
+enum class AppIconPreset(private val componentName: String, @DrawableRes val iconPreviewResId: Int, @StringRes val labelResId: Int) {
+ DEFAULT(".RoutingActivity", R.drawable.ic_app_icon_default_top_preview, R.string.app_name),
+ WHITE(".RoutingActivityAltWhite", R.drawable.ic_app_icon_signal_white_top_preview, R.string.app_name),
+ COLOR(".RoutingActivityAltColor", R.drawable.ic_app_icon_signal_color_top_preview, R.string.app_name),
+ DARK(".RoutingActivityAltDark", R.drawable.ic_app_icon_signal_dark_top_preview, R.string.app_name),
+ DARK_VARIANT(".RoutingActivityAltDarkVariant", R.drawable.ic_app_icon_signal_dark_variant_top_preview, R.string.app_name),
+ CHAT(".RoutingActivityAltChat", R.drawable.ic_app_icon_chat_top_preview, R.string.app_name),
+ BUBBLES(".RoutingActivityAltBubbles", R.drawable.ic_app_icon_bubbles_top_preview, R.string.app_name),
+ YELLOW(".RoutingActivityAltYellow", R.drawable.ic_app_icon_yellow_top_preview, R.string.app_name),
+ NEWS(".RoutingActivityAltNews", R.drawable.ic_app_icon_news_top_preview, R.string.app_icon_label_news),
+ NOTES(".RoutingActivityAltNotes", R.drawable.ic_app_icon_notes_top_preview, R.string.app_icon_label_notes),
+ WEATHER(".RoutingActivityAltWeather", R.drawable.ic_app_icon_weather_top_preview, R.string.app_icon_label_weather),
+ WAVES(".RoutingActivityAltWaves", R.drawable.ic_app_icon_waves_top_preview, R.string.app_icon_label_waves);
+
+ fun getComponentName(context: Context): ComponentName {
+ val applicationContext = context.applicationContext
+ return ComponentName(applicationContext, applicationContext.packageName + componentName)
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconUtility.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconUtility.kt
new file mode 100644
index 0000000000..7598db44ba
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/appearance/appicon/util/AppIconUtility.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.components.settings.app.appearance.appicon.util
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import org.signal.core.util.logging.Log
+
+class AppIconUtility(context: Context) {
+ private val applicationContext: Context = context.applicationContext
+ private val pm = applicationContext.packageManager
+
+ val currentAppIcon by lazy { readCurrentAppIconFromPackageManager() }
+
+ fun isCurrentlySelected(preset: AppIconPreset): Boolean {
+ return preset == currentAppIcon
+ }
+
+ fun currentAppIconComponentName(): ComponentName {
+ return currentAppIcon.getComponentName(applicationContext) ?: AppIconPreset.DEFAULT.getComponentName(applicationContext)
+ }
+
+ fun setNewAppIcon(desiredAppIcon: AppIconPreset) {
+ currentAppIcon.let {
+ pm.setComponentEnabledSetting(it.getComponentName(applicationContext), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
+ }
+ pm.setComponentEnabledSetting(desiredAppIcon.getComponentName(applicationContext), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
+ }
+
+ private fun readCurrentAppIconFromPackageManager(): AppIconPreset {
+ val activeIcon = enumValues().firstOrNull {
+ val componentName = it.getComponentName(applicationContext)
+ val componentEnabledSetting = pm.getComponentEnabledSetting(componentName)
+
+ Log.d(TAG, "Found $componentName with state of $componentEnabledSetting")
+ if (it == AppIconPreset.DEFAULT && componentEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ return it
+ }
+
+ componentEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ }
+
+ return if (activeIcon == null) {
+ setNewAppIcon(AppIconPreset.DEFAULT)
+ AppIconPreset.DEFAULT
+ } else {
+ activeIcon
+ }
+ }
+
+ companion object {
+ private const val TAG = "AppIconUtility"
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java
index 42e8752a40..4f7f5dc0e6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java
@@ -17,6 +17,7 @@ import com.google.common.collect.Sets;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.components.settings.app.appearance.appicon.util.AppIconUtility;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
@@ -173,8 +174,10 @@ public final class ConversationUtil {
List shortcuts = new ArrayList<>(rankedRecipients.size());
+ ComponentName activityName = new AppIconUtility(context).currentAppIconComponentName();
+
for (int i = 0; i < rankedRecipients.size(); i++) {
- ShortcutInfoCompat info = buildShortcutInfo(context, rankedRecipients.get(i), i, Direction.NONE);
+ ShortcutInfoCompat info = buildShortcutInfo(context, activityName, rankedRecipients.get(i), i, Direction.NONE);
shortcuts.add(info);
}
@@ -188,7 +191,10 @@ public final class ConversationUtil {
*/
@WorkerThread
private static boolean pushShortcutForRecipientInternal(@NonNull Context context, @NonNull Recipient recipient, int rank, @NonNull Direction direction) {
- ShortcutInfoCompat shortcutInfo = buildShortcutInfo(context, recipient, rank, direction);
+
+ ComponentName activityName = new AppIconUtility(context).currentAppIconComponentName();
+
+ ShortcutInfoCompat shortcutInfo = buildShortcutInfo(context, activityName, recipient, rank, direction);
return ShortcutManagerCompat.pushDynamicShortcut(context, shortcutInfo);
}
@@ -203,6 +209,7 @@ public final class ConversationUtil {
*/
@WorkerThread
private static @NonNull ShortcutInfoCompat buildShortcutInfo(@NonNull Context context,
+ @NonNull ComponentName activity,
@NonNull Recipient recipient,
int rank,
@NonNull Direction direction)
@@ -222,7 +229,7 @@ public final class ConversationUtil {
.setIcon(AvatarUtil.getIconCompatForShortcut(context, resolved))
.setPersons(persons)
.setCategories(Sets.newHashSet(CATEGORY_SHARE_TARGET))
- .setActivity(new ComponentName(context, "org.thoughtcrime.securesms.RoutingActivity"))
+ .setActivity(activity)
.setRank(rank)
.setLocusId(new LocusIdCompat(shortcutId));
diff --git a/app/src/main/res/drawable/app_icon_tutorial_apps_homescreen.xml b/app/src/main/res/drawable/app_icon_tutorial_apps_homescreen.xml
new file mode 100644
index 0000000000..94da2823a7
--- /dev/null
+++ b/app/src/main/res/drawable/app_icon_tutorial_apps_homescreen.xml
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/app_icon_tutorial_notification.xml b/app/src/main/res/drawable/app_icon_tutorial_notification.xml
new file mode 100644
index 0000000000..64c94da98e
--- /dev/null
+++ b/app/src/main/res/drawable/app_icon_tutorial_notification.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_bubbles_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_bubbles_top_preview.xml
new file mode 100644
index 0000000000..80795c454f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_bubbles_top_preview.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_chat_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_chat_top_preview.xml
new file mode 100644
index 0000000000..b35efd30a4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_chat_top_preview.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_default_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_default_top_preview.xml
new file mode 100644
index 0000000000..0f6ff2eb05
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_default_top_preview.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_news_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_news_top_preview.xml
new file mode 100644
index 0000000000..9cc1ae4881
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_news_top_preview.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_notes_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_notes_top_preview.xml
new file mode 100644
index 0000000000..11b1e420da
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_notes_top_preview.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_signal_color_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_signal_color_top_preview.xml
new file mode 100644
index 0000000000..54264ce8d0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_signal_color_top_preview.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_signal_dark_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_signal_dark_top_preview.xml
new file mode 100644
index 0000000000..23be53fe3a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_signal_dark_top_preview.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_signal_dark_variant_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_signal_dark_variant_top_preview.xml
new file mode 100644
index 0000000000..2d4267b7ab
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_signal_dark_variant_top_preview.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_signal_default_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_signal_default_top_preview.xml
new file mode 100644
index 0000000000..b2d822b2f8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_signal_default_top_preview.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_signal_white_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_signal_white_top_preview.xml
new file mode 100644
index 0000000000..08298b4a75
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_signal_white_top_preview.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_waves_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_waves_top_preview.xml
new file mode 100644
index 0000000000..79fcddab50
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_waves_top_preview.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_weather_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_weather_top_preview.xml
new file mode 100644
index 0000000000..d2635dcd16
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_weather_top_preview.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_app_icon_yellow_top_preview.xml b/app/src/main/res/drawable/ic_app_icon_yellow_top_preview.xml
new file mode 100644
index 0000000000..29d5b9dcd1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_app_icon_yellow_top_preview.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_bubbles_background.xml b/app/src/main/res/drawable/ic_launcher_alt_bubbles_background.xml
new file mode 100644
index 0000000000..16ac8107eb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_bubbles_background.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_bubbles_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_bubbles_foreground.xml
new file mode 100644
index 0000000000..9b2b48d277
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_bubbles_foreground.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_bubbles_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_bubbles_monochrome.xml
new file mode 100644
index 0000000000..b0849b5584
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_bubbles_monochrome.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_chat_background.xml b/app/src/main/res/drawable/ic_launcher_alt_chat_background.xml
new file mode 100644
index 0000000000..cda1a5ab3f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_chat_background.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_chat_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_chat_foreground.xml
new file mode 100644
index 0000000000..fa2ab7db41
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_chat_foreground.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_chat_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_chat_monochrome.xml
new file mode 100644
index 0000000000..ebf5ec2ebb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_chat_monochrome.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_news_background.xml b/app/src/main/res/drawable/ic_launcher_alt_news_background.xml
new file mode 100644
index 0000000000..5bfd27384d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_news_background.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_news_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_news_foreground.xml
new file mode 100644
index 0000000000..f6bd7cd284
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_news_foreground.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_news_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_news_monochrome.xml
new file mode 100644
index 0000000000..31bd93800f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_news_monochrome.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_notes_background.xml b/app/src/main/res/drawable/ic_launcher_alt_notes_background.xml
new file mode 100644
index 0000000000..1c2abe0c8b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_notes_background.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_notes_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_notes_foreground.xml
new file mode 100644
index 0000000000..07b8e13bcd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_notes_foreground.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_notes_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_notes_monochrome.xml
new file mode 100644
index 0000000000..f1dbbc47f4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_notes_monochrome.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_color_background.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_color_background.xml
new file mode 100644
index 0000000000..4587126d03
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_color_background.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_color_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_color_foreground.xml
new file mode 100644
index 0000000000..18df352373
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_color_foreground.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_dark_background.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_background.xml
new file mode 100644
index 0000000000..92bd06366b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_background.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_dark_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_foreground.xml
new file mode 100644
index 0000000000..ba5e0f3e3b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_foreground.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_background.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_background.xml
new file mode 100644
index 0000000000..5bb7f7ad86
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_background.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_foreground.xml
new file mode 100644
index 0000000000..f103504179
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_dark_variant_foreground.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_white_background.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_white_background.xml
new file mode 100644
index 0000000000..3ca7095395
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_white_background.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_signal_white_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_signal_white_foreground.xml
new file mode 100644
index 0000000000..76a6861d0f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_signal_white_foreground.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_waves_background.xml b/app/src/main/res/drawable/ic_launcher_alt_waves_background.xml
new file mode 100644
index 0000000000..654f4fd98b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_waves_background.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_waves_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_waves_foreground.xml
new file mode 100644
index 0000000000..0916fc01ed
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_waves_foreground.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_waves_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_waves_monochrome.xml
new file mode 100644
index 0000000000..e04d1da443
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_waves_monochrome.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_weather_background.xml b/app/src/main/res/drawable/ic_launcher_alt_weather_background.xml
new file mode 100644
index 0000000000..e286725d7d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_weather_background.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_weather_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_weather_foreground.xml
new file mode 100644
index 0000000000..3e107964ad
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_weather_foreground.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_weather_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_weather_monochrome.xml
new file mode 100644
index 0000000000..b3e1991d54
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_weather_monochrome.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_yellow_background.xml b/app/src/main/res/drawable/ic_launcher_alt_yellow_background.xml
new file mode 100644
index 0000000000..996ada4c34
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_yellow_background.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_yellow_foreground.xml b/app/src/main/res/drawable/ic_launcher_alt_yellow_foreground.xml
new file mode 100644
index 0000000000..09a47f54a1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_yellow_foreground.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_alt_yellow_monochrome.xml b/app/src/main/res/drawable/ic_launcher_alt_yellow_monochrome.xml
new file mode 100644
index 0000000000..ebf5ec2ebb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_alt_yellow_monochrome.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
index c521e002c2..77f3eec8fa 100644
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -8,7 +8,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_app_icon_settings.xml b/app/src/main/res/layout/activity_app_icon_settings.xml
new file mode 100644
index 0000000000..f7b8965584
--- /dev/null
+++ b/app/src/main/res/layout/activity_app_icon_settings.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_bubbles.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_bubbles.xml
new file mode 100644
index 0000000000..78eae4fa8e
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_bubbles.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_chat.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_chat.xml
new file mode 100644
index 0000000000..e7d0a4ab86
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_chat.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_news.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_news.xml
new file mode 100644
index 0000000000..d2798924c3
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_news.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_notes.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_notes.xml
new file mode 100644
index 0000000000..a9b905988f
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_notes.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_color.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_color.xml
new file mode 100644
index 0000000000..df0e8dd73d
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_color.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark.xml
new file mode 100644
index 0000000000..3752ec25e3
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark_variant.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark_variant.xml
new file mode 100644
index 0000000000..d217d0f080
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_dark_variant.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_white.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_white.xml
new file mode 100644
index 0000000000..d4aff19ff4
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_signal_white.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_waves.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_waves.xml
new file mode 100644
index 0000000000..e3f14bcad5
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_waves.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_weather.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_weather.xml
new file mode 100644
index 0000000000..b5ca6467fb
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_weather.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_yellow.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_yellow.xml
new file mode 100644
index 0000000000..b2cdd306fa
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_alt_yellow.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/app_settings.xml b/app/src/main/res/navigation/app_settings.xml
index 5948721801..fed1e0d2bf 100644
--- a/app/src/main/res/navigation/app_settings.xml
+++ b/app/src/main/res/navigation/app_settings.xml
@@ -237,6 +237,14 @@
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5fa589b92b..f9442e111d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -24,6 +24,15 @@
Save
Note to Self
+
+ Weather
+
+ Notes
+
+ News
+
+ Waves
+
\+%d
@@ -2884,6 +2893,28 @@
Appearance
Theme
Chat color & wallpaper
+
+ App Icon
+
+ OK
+
+ Cancel
+
+ Change app icon and name to \"%1$s\"
+
+ Signal will need to close to change the app icon and name. Notifications will always display the default Signal icon and name.
+
+ Select an app icon and name, which will be visible on your phone\'s home screen and app drawer. Notifications will always display the default Signal icon and name. Learn\u00A0more
+
+ App icons and names are visible on the home screen and app drawer.
+
+ Notifications will always display the default Signal icon and name.
+
+ Learn\u00A0more
+
+ Icon for %1$s
+
+ Graphic illustrating where the replacement app icon will be visible.
Disable PIN
Enable PIN
If you disable the PIN, you will lose all data when you re-register Signal unless you manually back up and restore. You can not turn on Registration Lock while the PIN is disabled.