From c2c4c9f41a8aa6bfdfba0146f8b8cdd5985d6707 Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Thu, 3 Sep 2020 22:15:03 +1000 Subject: [PATCH 01/69] New avatar placeholder drawable generator. --- ...profile_picture_view_medium_background.xml | 2 - ...ile_picture_view_rss_medium_background.xml | 2 - .../profile_picture_view_small_background.xml | 2 - res/layout/activity_home.xml | 3 +- res/layout/activity_settings.xml | 3 +- res/layout/view_profile_picture.xml | 27 +----- res/values/colors.xml | 8 ++ .../conversation/ConversationItem.java | 1 + .../securesms/loki/activities/HomeActivity.kt | 14 ++-- .../loki/activities/SettingsActivity.kt | 5 +- .../loki/todo/AvatarPlaceholderGenerator.kt | 83 +++++++++++++++++++ .../securesms/loki/views/ConversationView.kt | 26 ++++-- .../loki/views/MentionCandidateView.kt | 1 + .../loki/views/ProfilePictureView.kt | 67 ++++++++++----- .../securesms/loki/views/UserView.kt | 3 + 15 files changed, 181 insertions(+), 66 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt diff --git a/res/drawable/profile_picture_view_medium_background.xml b/res/drawable/profile_picture_view_medium_background.xml index 287d6298e2..143223ac1b 100644 --- a/res/drawable/profile_picture_view_medium_background.xml +++ b/res/drawable/profile_picture_view_medium_background.xml @@ -6,6 +6,4 @@ - - \ No newline at end of file diff --git a/res/drawable/profile_picture_view_rss_medium_background.xml b/res/drawable/profile_picture_view_rss_medium_background.xml index b060c41b4b..4d9a6a86d9 100644 --- a/res/drawable/profile_picture_view_rss_medium_background.xml +++ b/res/drawable/profile_picture_view_rss_medium_background.xml @@ -6,6 +6,4 @@ - - \ No newline at end of file diff --git a/res/drawable/profile_picture_view_small_background.xml b/res/drawable/profile_picture_view_small_background.xml index 2f44fefe9f..523316cf4e 100644 --- a/res/drawable/profile_picture_view_small_background.xml +++ b/res/drawable/profile_picture_view_small_background.xml @@ -6,6 +6,4 @@ - - \ No newline at end of file diff --git a/res/layout/activity_home.xml b/res/layout/activity_home.xml index 13eb8bda5e..b9dee38117 100644 --- a/res/layout/activity_home.xml +++ b/res/layout/activity_home.xml @@ -34,7 +34,8 @@ android:layout_height="@dimen/small_profile_picture_size" android:layout_alignParentLeft="true" android:layout_centerVertical="true" - android:layout_marginLeft="9dp" /> + android:layout_marginLeft="9dp" + android:foreground="@drawable/circle_touch_highlight_background"/> + android:layout_marginTop="@dimen/medium_spacing" + android:foreground="@drawable/circle_touch_highlight_background" /> - + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - @@ -60,11 +51,6 @@ android:layout_height="match_parent" android:background="@drawable/profile_picture_view_medium_background" /> - - - - \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index c9356d308b..390c3be09e 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -107,4 +107,12 @@ #121212 #171717 + + #18da80 + #ee8917 + #239edf + #c33fe9 + #83b433 + + diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java index ca3d10db17..ed4f24d110 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -804,6 +804,7 @@ public class ConversationItem extends LinearLayout bodyBubble.setLayoutParams(layoutParams); if (profilePictureView == null) return; profilePictureView.setPublicKey(recipient.getAddress().toString()); + profilePictureView.setDisplayName(recipient.getName()); profilePictureView.setAdditionalPublicKey(null); profilePictureView.setRSSFeed(false); profilePictureView.setGlide(glideRequests); diff --git a/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt index 43e0647d2d..af6f3b9979 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms.loki.activities import android.app.AlertDialog -import androidx.lifecycle.Observer import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -11,10 +10,6 @@ import android.net.Uri import android.os.AsyncTask import android.os.Bundle import android.os.Handler -import androidx.loader.app.LoaderManager -import androidx.loader.content.Loader -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import androidx.recyclerview.widget.LinearLayoutManager import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan @@ -22,6 +17,11 @@ import android.util.DisplayMetrics import android.view.View import android.widget.RelativeLayout import android.widget.Toast +import androidx.lifecycle.Observer +import androidx.loader.app.LoaderManager +import androidx.loader.content.Loader +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_home.* import network.loki.messenger.R import org.thoughtcrime.securesms.ApplicationContext @@ -42,14 +42,13 @@ import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegat import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests -import org.thoughtcrime.securesms.util.GroupUtil import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol -import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol +import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol import org.whispersystems.signalservice.loki.protocol.shelved.syncmessages.SyncMessagesProtocol import org.whispersystems.signalservice.loki.utilities.toHexString @@ -98,6 +97,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe // Set up toolbar buttons profileButton.glide = glide profileButton.publicKey = publicKey + profileButton.displayName = TextSecurePreferences.getProfileName(this) profileButton.update() profileButton.setOnClickListener { openSettings() } pathStatusViewContainer.setOnClickListener { showPath() } diff --git a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index 1a88113784..0d052d4221 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -74,14 +74,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { setContentView(R.layout.activity_settings) + val origUserDisplayName = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey) + glide = GlideApp.with(this) profilePictureView.glide = glide profilePictureView.publicKey = hexEncodedPublicKey + profilePictureView.displayName = displayNameToBeUploaded profilePictureView.isLarge = true profilePictureView.update() profilePictureView.setOnClickListener { showEditProfilePictureUI() } ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) } - btnGroupNameDisplay.text = DatabaseFactory.getLokiUserDatabase(this).getDisplayName(hexEncodedPublicKey) + btnGroupNameDisplay.text = origUserDisplayName publicKeyTextView.text = hexEncodedPublicKey copyButton.setOnClickListener { copyPublicKey() } shareButton.setOnClickListener { sharePublicKey() } diff --git a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt new file mode 100644 index 0000000000..bca93db549 --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt @@ -0,0 +1,83 @@ +package org.thoughtcrime.securesms.loki.todo + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.BitmapDrawable +import android.text.TextPaint +import android.text.TextUtils +import androidx.annotation.ColorInt +import androidx.core.graphics.ColorUtils +import network.loki.messenger.R +import java.util.* + +object AvatarPlaceholderGenerator { + + private const val EMPTY_LABEL = "0"; + + private val tmpFloatArray = FloatArray(3) + + fun generate(context: Context, pixelSize: Int, hashString: String, displayName: String?): BitmapDrawable { + //TODO That should be replaced with a proper hash extraction code. + val hash: Long + val hexRegex = Regex("^[0-9A-Fa-f]+\$") + if (hashString.length >= 12 && hashString.matches(hexRegex)) { + hash = hashString.substring(0 until 12).toLong(16) + } else { + hash = hashString.toLong() + } + + // Do not cache color array, it may be different depends on the current theme. + val colorArray = context.resources.getIntArray(R.array.user_pic_placeholder_primary) + val colorPrimary = colorArray[(hash % colorArray.size).toInt()] + val colorSecondary = changeColorHueBy(colorPrimary, 16f) + + val labelText = when { + !TextUtils.isEmpty(displayName) -> extractLabel(displayName!!) + !TextUtils.isEmpty(hashString) -> extractLabel(hashString) + else -> EMPTY_LABEL + } + + val bitmap = Bitmap.createBitmap(pixelSize, pixelSize, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + + // Draw background/frame + val paint = Paint() + paint.isAntiAlias = true + paint.shader = LinearGradient(0f, 0f, 0f, pixelSize.toFloat(), + colorPrimary, + colorSecondary, + Shader.TileMode.REPEAT) + canvas.drawCircle(pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, paint) + + // Draw text + val textPaint = TextPaint() + textPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) + textPaint.isAntiAlias = true + textPaint.textSize = pixelSize * 0.5f + textPaint.color = Color.WHITE + val areaRect = Rect(0, 0, pixelSize, pixelSize) + val textBounds = RectF(areaRect) + textBounds.right = textPaint.measureText(labelText) + textBounds.bottom = textPaint.descent() - textPaint.ascent() + textBounds.left += (areaRect.width() - textBounds.right) * 0.5f + textBounds.top += (areaRect.height() - textBounds.bottom) * 0.5f + canvas.drawText(labelText, textBounds.left, textBounds.top - textPaint.ascent(), textPaint) + + return BitmapDrawable(context.resources, bitmap) + } + + @ColorInt + private fun changeColorHueBy(@ColorInt color: Int, hueDelta: Float): Int { + val hslColor = tmpFloatArray + ColorUtils.colorToHSL(color, hslColor) + hslColor[0] = (hslColor[0] + hueDelta) % 360f + return ColorUtils.HSLToColor(hslColor) + } + + private fun extractLabel(content: String): String { + var content = content.trim() + if (content.isEmpty()) return EMPTY_LABEL + + return content.first().toString().toUpperCase(Locale.ROOT) + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt b/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt index 382ac63a84..181598b730 100644 --- a/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/ConversationView.kt @@ -2,12 +2,14 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context import android.graphics.Typeface +import android.text.TextUtils import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_conversation.view.* import network.loki.messenger.R +import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.ThreadRecord import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions @@ -58,22 +60,29 @@ class ConversationView : LinearLayout { if (thread.recipient.isGroupRecipient) { if ("Session Public Chat" == thread.recipient.name) { profilePictureView.publicKey = "" + profilePictureView.displayName = "" profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = true } else { - val users = MentionsManager.shared.userPublicKeyCache[thread.threadId]?.toMutableList() ?: mutableListOf() - users.remove(TextSecurePreferences.getLocalNumber(context)) + val userKeys = MentionsManager.shared.userPublicKeyCache[thread.threadId]?.toMutableList() ?: mutableListOf() + userKeys.remove(TextSecurePreferences.getLocalNumber(context)) val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) if (masterPublicKey != null) { - users.remove(masterPublicKey) + userKeys.remove(masterPublicKey) } - val randomUsers = users.sorted() // Sort to provide a level of stability - profilePictureView.publicKey = randomUsers.getOrNull(0) ?: "" - profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: "" + + val sortedUserKeys = userKeys.sorted() // Sort to provide a level of stability + val userKey0 = sortedUserKeys.getOrNull(0) ?: "" + val userKey1 = sortedUserKeys.getOrNull(1) ?: "" + profilePictureView.publicKey = userKey0 + profilePictureView.displayName = getUserDisplayName(userKey0) + profilePictureView.additionalPublicKey = userKey1 + profilePictureView.additionalDisplayName = getUserDisplayName(userKey1) profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Session Updates" } } else { profilePictureView.publicKey = thread.recipient.address.toString() + profilePictureView.displayName = thread.recipient.name profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false } @@ -103,5 +112,10 @@ class ConversationView : LinearLayout { else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check) } } + + private fun getUserDisplayName(publicKey: String?): String? { + if (TextUtils.isEmpty(publicKey)) return null + return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!) + } // endregion } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt b/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt index 1e6a0d057c..a9b62a5fd9 100644 --- a/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt @@ -32,6 +32,7 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: private fun update() { btnGroupNameDisplay.text = mentionCandidate.displayName profilePictureView.publicKey = mentionCandidate.publicKey + profilePictureView.displayName = mentionCandidate.displayName profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false profilePictureView.glide = glide!! diff --git a/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt b/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt index 362f5ff35d..d70f20fdc2 100644 --- a/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt @@ -1,18 +1,18 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context -import androidx.annotation.DimenRes import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.widget.ImageView import android.widget.RelativeLayout +import androidx.annotation.DimenRes import com.bumptech.glide.load.engine.DiskCacheStrategy import kotlinx.android.synthetic.main.view_profile_picture.view.* import network.loki.messenger.R import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto import org.thoughtcrime.securesms.database.Address -import org.thoughtcrime.securesms.loki.todo.JazzIdenticonDrawable +import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.TextSecurePreferences @@ -22,7 +22,9 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences class ProfilePictureView : RelativeLayout { lateinit var glide: GlideRequests var publicKey: String? = null + var displayName: String? = null var additionalPublicKey: String? = null + var additionalDisplayName: String? = null var isRSSFeed = false var isLarge = false @@ -58,28 +60,51 @@ class ProfilePictureView : RelativeLayout { singleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE largeSingleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && isLarge) View.VISIBLE else View.INVISIBLE rssImageView.visibility = if (isRSSFeed) View.VISIBLE else View.INVISIBLE - fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String, @DimenRes sizeID: Int) { - glide.clear(imageView) - if (hexEncodedPublicKey.isNotEmpty()) { - val recipient = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false); - val signalProfilePicture = recipient.contactPhoto - if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") { - glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) - } else { - val size = resources.getDimensionPixelSize(sizeID) - val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) - val hepk = if (recipient.isLocalNumber && masterHexEncodedPublicKey != null) masterHexEncodedPublicKey else hexEncodedPublicKey - val jazzIcon = JazzIdenticonDrawable(size, size, hepk) - glide.load(jazzIcon).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) - } + + setProfilePictureIfNeeded( + doubleModeImageView1, + publicKey, + displayName, + R.dimen.small_profile_picture_size) + setProfilePictureIfNeeded( + doubleModeImageView2, + additionalPublicKey ?: "", + additionalDisplayName, + R.dimen.small_profile_picture_size) + setProfilePictureIfNeeded( + singleModeImageView, + publicKey, + displayName, + R.dimen.medium_profile_picture_size) + setProfilePictureIfNeeded( + largeSingleModeImageView, + publicKey, + displayName, + R.dimen.large_profile_picture_size) + } + + private fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String, displayName: String?, @DimenRes sizeResId: Int) { + glide.clear(imageView) + if (hexEncodedPublicKey.isNotEmpty()) { + val recipient = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false); + val signalProfilePicture = recipient.contactPhoto + if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") { + glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) } else { - imageView.setImageDrawable(null) + val sizePx = resources.getDimensionPixelSize(sizeResId) + val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) + val hepk = if (recipient.isLocalNumber && masterHexEncodedPublicKey != null) masterHexEncodedPublicKey else hexEncodedPublicKey +// val jazzIcon = JazzIdenticonDrawable(size, size, hepk) + glide.load(AvatarPlaceholderGenerator.generate( + context, + sizePx, + hepk, + displayName + )).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) } + } else { + imageView.setImageDrawable(null) } - setProfilePictureIfNeeded(doubleModeImageView1, publicKey, R.dimen.small_profile_picture_size) - setProfilePictureIfNeeded(doubleModeImageView2, additionalPublicKey ?: "", R.dimen.small_profile_picture_size) - setProfilePictureIfNeeded(singleModeImageView, publicKey, R.dimen.medium_profile_picture_size) - setProfilePictureIfNeeded(largeSingleModeImageView, publicKey, R.dimen.large_profile_picture_size) } // endregion } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/views/UserView.kt b/src/org/thoughtcrime/securesms/loki/views/UserView.kt index 9619a90389..2347f07cc9 100644 --- a/src/org/thoughtcrime/securesms/loki/views/UserView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/UserView.kt @@ -51,6 +51,7 @@ class UserView : LinearLayout { if (user.isGroupRecipient) { if ("Session Public Chat" == user.name || user.address.isRSSFeed) { profilePictureView.publicKey = "" + profilePictureView.displayName = null profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = true } else { @@ -58,11 +59,13 @@ class UserView : LinearLayout { val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf() val randomUsers = users.sorted() // Sort to provide a level of stability profilePictureView.publicKey = randomUsers.getOrNull(0) ?: "" + profilePictureView.displayName = null profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: "" profilePictureView.isRSSFeed = false } } else { profilePictureView.publicKey = address + profilePictureView.displayName = null profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false } From 3e82c8f9ea288bdd3815a2b8bc1065972d16272c Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Fri, 4 Sep 2020 00:08:34 +1000 Subject: [PATCH 02/69] User pic placeholder colors tweaks. Use proper username for settings activity placeholder. --- res/values/colors.xml | 7 +++---- .../securesms/loki/activities/SettingsActivity.kt | 2 +- .../securesms/loki/todo/AvatarPlaceholderGenerator.kt | 8 +++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/res/values/colors.xml b/res/values/colors.xml index 390c3be09e..caaccd140b 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -108,11 +108,10 @@ #171717 - #18da80 - #ee8917 + #2bca81 + #ee7117 #239edf - #c33fe9 - #83b433 + #bb35e9 diff --git a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index 0d052d4221..efd7836ffe 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -79,7 +79,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { glide = GlideApp.with(this) profilePictureView.glide = glide profilePictureView.publicKey = hexEncodedPublicKey - profilePictureView.displayName = displayNameToBeUploaded + profilePictureView.displayName = origUserDisplayName profilePictureView.isLarge = true profilePictureView.update() profilePictureView.setOnClickListener { showEditProfilePictureUI() } diff --git a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt index bca93db549..d79f736c89 100644 --- a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt +++ b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt @@ -29,7 +29,7 @@ object AvatarPlaceholderGenerator { // Do not cache color array, it may be different depends on the current theme. val colorArray = context.resources.getIntArray(R.array.user_pic_placeholder_primary) val colorPrimary = colorArray[(hash % colorArray.size).toInt()] - val colorSecondary = changeColorHueBy(colorPrimary, 16f) + val colorSecondary = changeColorHueBy(colorPrimary, 12f) val labelText = when { !TextUtils.isEmpty(displayName) -> extractLabel(displayName!!) @@ -41,8 +41,7 @@ object AvatarPlaceholderGenerator { val canvas = Canvas(bitmap) // Draw background/frame - val paint = Paint() - paint.isAntiAlias = true + val paint = Paint(Paint.ANTI_ALIAS_FLAG) paint.shader = LinearGradient(0f, 0f, 0f, pixelSize.toFloat(), colorPrimary, colorSecondary, @@ -50,9 +49,8 @@ object AvatarPlaceholderGenerator { canvas.drawCircle(pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, pixelSize.toFloat() / 2, paint) // Draw text - val textPaint = TextPaint() + val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG) textPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) - textPaint.isAntiAlias = true textPaint.textSize = pixelSize * 0.5f textPaint.color = Color.WHITE val areaRect = Rect(0, 0, pixelSize, pixelSize) From 8f2fc3ab74c0e31c3880b04660eb543841eee009 Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Fri, 4 Sep 2020 00:30:14 +1000 Subject: [PATCH 03/69] New user avatar placeholder for message received notification. --- .../SingleRecipientNotificationBuilder.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index bc5f695a35..29fab4e4c3 100644 --- a/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/src/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator; import org.thoughtcrime.securesms.loki.utilities.NotificationUtilities; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.GlideApp; @@ -80,9 +81,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil addPerson(recipient.getContactUri().toString()); } - ContactPhoto contactPhoto = recipient.getContactPhoto(); - FallbackContactPhoto fallbackContactPhoto = recipient.getFallbackContactPhoto(); - + ContactPhoto contactPhoto = recipient.getContactPhoto(); if (contactPhoto != null) { try { setLargeIcon(GlideApp.with(context.getApplicationContext()) @@ -94,10 +93,10 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil .get()); } catch (InterruptedException | ExecutionException e) { Log.w(TAG, e); - setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context))); + setLargeIcon(obtainAvatarPlaceholderDrawable(context, recipient)); } } else { - setLargeIcon(fallbackContactPhoto.asDrawable(context, recipient.getColor().toConversationColor(context))); + setLargeIcon(obtainAvatarPlaceholderDrawable(context, recipient)); } } else { @@ -321,4 +320,14 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil return content; } + private static Drawable obtainAvatarPlaceholderDrawable(Context context, Recipient recipient) { + //TODO Copied from ProfilePictureView#setProfilePictureIfNeeded + // Refactor this code to use the same recipient placeholder generator method across the app. + String publicKey = recipient.getAddress().serialize(); + String hepk = (recipient.isLocalNumber() && publicKey != null) + ? TextSecurePreferences.getMasterHexEncodedPublicKey(context) + : publicKey; + String displayName = recipient.getName(); + return AvatarPlaceholderGenerator.INSTANCE.generate(context, 128, hepk, displayName); + } } From ad67f478c8ce5c6464dcb03705c9237aadc2493b Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Fri, 4 Sep 2020 01:00:06 +1000 Subject: [PATCH 04/69] Use proper radix for the public key number conversion. --- .../securesms/loki/todo/AvatarPlaceholderGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt index d79f736c89..4596efd203 100644 --- a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt +++ b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt @@ -23,7 +23,7 @@ object AvatarPlaceholderGenerator { if (hashString.length >= 12 && hashString.matches(hexRegex)) { hash = hashString.substring(0 until 12).toLong(16) } else { - hash = hashString.toLong() + hash = hashString.toLong(16) } // Do not cache color array, it may be different depends on the current theme. From d3e895eac6fadbdfa80bc2c8af0357cd4336b880 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 4 Sep 2020 10:58:57 +1000 Subject: [PATCH 05/69] Don't append short IDs to display names --- .../loki/protocol/SessionMetaProtocol.kt | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt index a7acaa25fe..9f9a38427d 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt @@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.TextSecurePreferences import org.whispersystems.signalservice.api.messages.SignalServiceContent import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage -import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol import java.security.MessageDigest object SessionMetaProtocol { @@ -37,24 +36,16 @@ object SessionMetaProtocol { @JvmStatic fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) { - val rawDisplayName = content.senderDisplayName.orNull() ?: return - if (rawDisplayName.isBlank()) { return } + val displayName = content.senderDisplayName.orNull() ?: return + if (displayName.isBlank()) { return } val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) val sender = content.sender.toLowerCase() if (userMasterPublicKey == sender) { // Update the user's local name if the message came from their master device - TextSecurePreferences.setProfileName(context, rawDisplayName) - } - // Don't overwrite if the message came from a linked device; the device name is - // stored as a user name - val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey) - if (!allUserDevices.contains(sender)) { - val displayName = rawDisplayName + " (..." + sender.substring(sender.length - 8) + ")" - DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, displayName) - } else { - DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, rawDisplayName) + TextSecurePreferences.setProfileName(context, displayName) } + DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, displayName) } @JvmStatic From 31916a95d52b72f5186d9b52e1179522ae08f78e Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 4 Sep 2020 11:32:43 +1000 Subject: [PATCH 06/69] Don't show Session ID in conversation title view --- res/values-small/dimens.xml | 2 +- res/values/dimens.xml | 2 +- .../conversation/ConversationActivity.java | 14 +------------- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/res/values-small/dimens.xml b/res/values-small/dimens.xml index 4775251f06..81c5c4100b 100644 --- a/res/values-small/dimens.xml +++ b/res/values-small/dimens.xml @@ -8,7 +8,7 @@ 13sp 15sp 20sp - 25sp + 24sp 50sp diff --git a/res/values/dimens.xml b/res/values/dimens.xml index d255ee2585..1c0282a999 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -8,7 +8,7 @@ 15sp 17sp 22sp - 27sp + 26sp 50sp diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 4a06575a30..02a68f3e2c 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -3103,15 +3103,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void updateSubtitleTextView() { muteIndicatorImageView.setVisibility(View.GONE); subtitleTextView.setVisibility(View.VISIBLE); - if (messageStatus != null) { - switch (messageStatus) { - case "calculatingPoW": subtitleTextView.setText("Encrypting message"); break; - case "contactingNetwork": subtitleTextView.setText("Tracing a path"); break; - case "sendingMessage": subtitleTextView.setText("Sending message"); break; - case "messageSent": subtitleTextView.setText("Message sent securely"); break; - case "messageFailed": subtitleTextView.setText("Message failed to send"); break; - } - } else if (recipient.isMuted()) { + if (recipient.isMuted()) { muteIndicatorImageView.setVisibility(View.VISIBLE); subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault())); } else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) { @@ -3125,10 +3117,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } else { subtitleTextView.setVisibility(View.GONE); } - } else if (PublicKeyValidation.isValid(recipient.getAddress().toString())) { - String ourMasterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this); - String hexEncodedPublicKey = (recipient.isLocalNumber() && ourMasterHexEncodedPublicKey != null) ? ourMasterHexEncodedPublicKey : recipient.getAddress().toPhoneString(); - subtitleTextView.setText(hexEncodedPublicKey); } else { subtitleTextView.setVisibility(View.GONE); } From f9b11665878eb92ce96a9406d393ca4c78a1835b Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Fri, 4 Sep 2020 11:51:12 +1000 Subject: [PATCH 07/69] Do not parse public key to a number if it's shorter than 12 chars. --- .../securesms/loki/todo/AvatarPlaceholderGenerator.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt index 4596efd203..9cea1618fd 100644 --- a/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt +++ b/src/org/thoughtcrime/securesms/loki/todo/AvatarPlaceholderGenerator.kt @@ -19,11 +19,10 @@ object AvatarPlaceholderGenerator { fun generate(context: Context, pixelSize: Int, hashString: String, displayName: String?): BitmapDrawable { //TODO That should be replaced with a proper hash extraction code. val hash: Long - val hexRegex = Regex("^[0-9A-Fa-f]+\$") - if (hashString.length >= 12 && hashString.matches(hexRegex)) { + if (hashString.length >= 12 && hashString.matches(Regex("^[0-9A-Fa-f]+\$"))) { hash = hashString.substring(0 until 12).toLong(16) } else { - hash = hashString.toLong(16) + hash = 0 } // Do not cache color array, it may be different depends on the current theme. From b14cf5fcf86bdd6b3dc2e3b31e391079414fc536 Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Fri, 4 Sep 2020 13:57:20 +1000 Subject: [PATCH 08/69] Fixed there's no label for the UserView's avatar placeholder. --- .../securesms/loki/views/UserView.kt | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/org/thoughtcrime/securesms/loki/views/UserView.kt b/src/org/thoughtcrime/securesms/loki/views/UserView.kt index 2347f07cc9..3b11082264 100644 --- a/src/org/thoughtcrime/securesms/loki/views/UserView.kt +++ b/src/org/thoughtcrime/securesms/loki/views/UserView.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.loki.views import android.content.Context +import android.text.TextUtils import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -8,6 +9,7 @@ import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_conversation.view.profilePictureView import kotlinx.android.synthetic.main.view_user.view.* import network.loki.messenger.R +import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.recipients.Recipient @@ -56,16 +58,20 @@ class UserView : LinearLayout { profilePictureView.isRSSFeed = true } else { val threadID = GroupManager.getThreadIDFromGroupID(address, context) - val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf() - val randomUsers = users.sorted() // Sort to provide a level of stability - profilePictureView.publicKey = randomUsers.getOrNull(0) ?: "" - profilePictureView.displayName = null - profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: "" + val userKeys = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf() + val sortedUserKeys = userKeys.sorted() // Sort to provide a level of stability + val userKey0 = sortedUserKeys.getOrNull(0) ?: "" + val userKey1 = sortedUserKeys.getOrNull(1) ?: "" + + profilePictureView.publicKey = userKey0 + profilePictureView.displayName = getUserDisplayName(userKey0) + profilePictureView.additionalPublicKey = userKey1 + profilePictureView.additionalDisplayName = getUserDisplayName(userKey1) profilePictureView.isRSSFeed = false } } else { profilePictureView.publicKey = address - profilePictureView.displayName = null + profilePictureView.displayName = getUserDisplayName(address) profilePictureView.additionalPublicKey = null profilePictureView.isRSSFeed = false } @@ -87,5 +93,10 @@ class UserView : LinearLayout { } } } + + private fun getUserDisplayName(publicKey: String?): String? { + if (TextUtils.isEmpty(publicKey)) return null + return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!) + } // endregion } \ No newline at end of file From db0fd21097c3ed66e9633c6aef745dbb0e0e2b3b Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 4 Sep 2020 14:58:45 +1000 Subject: [PATCH 09/69] Make text bubbles a bit smaller --- res/layout/conversation_item_received.xml | 42 +++++++++---------- res/layout/conversation_item_sent.xml | 36 ++++++++-------- res/layout/document_view.xml | 1 + res/layout/quote_view.xml | 3 +- .../conversation/ConversationItem.java | 11 ++--- 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml index 5b7d503cdf..063b5dd939 100644 --- a/res/layout/conversation_item_received.xml +++ b/res/layout/conversation_item_received.xml @@ -59,8 +59,8 @@ android:layout_height="wrap_content" android:layout_marginEnd="@dimen/massive_spacing" android:layout_marginStart="12dp" - android:paddingTop="@dimen/medium_spacing" - android:paddingBottom="@dimen/medium_spacing" + android:paddingTop="12dp" + android:paddingBottom="12dp" android:orientation="vertical" android:clipToPadding="false" android:clipChildren="false" @@ -71,9 +71,9 @@ android:id="@+id/group_sender_holder" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/message_bubble_horizontal_padding" - android:layout_marginBottom="@dimen/medium_spacing" - android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" + android:layout_marginStart="12dp" + android:layout_marginBottom="12dp" + android:layout_marginEnd="12dp" android:orientation="horizontal" android:visibility="gone" tools:visibility="visible"> @@ -113,9 +113,9 @@ android:id="@+id/quote_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/large_spacing" - android:layout_marginBottom="@dimen/medium_spacing" - android:layout_marginEnd="@dimen/large_spacing" + android:layout_marginStart="20dp" + android:layout_marginBottom="12dp" + android:layout_marginEnd="20dp" android:visibility="gone" app:message_type="incoming" app:quote_colorPrimary="@color/text" @@ -127,7 +127,7 @@ android:layout="@layout/conversation_item_received_shared_contact" android:layout_width="@dimen/media_bubble_default_dimens" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/message_bubble_top_padding" + android:layout_marginTop="12dp" android:visibility="gone"/> + android:layout_marginStart="12dp" + android:layout_marginBottom="4dp" + android:layout_marginEnd="12dp" /> + android:layout_marginStart="12dp" + android:layout_marginEnd="12dp" /> + android:layout_marginStart="12dp" + android:layout_marginBottom="4dp" + android:layout_marginEnd="12dp" /> + android:layout_marginEnd="12dp" /> diff --git a/res/layout/quote_view.xml b/res/layout/quote_view.xml index 50b270b500..8b1fa969df 100644 --- a/res/layout/quote_view.xml +++ b/res/layout/quote_view.xml @@ -73,7 +73,7 @@ android:layout_height="wrap_content" style="@style/Signal.Text.Body" android:textColor="@color/text" - android:textSize="@dimen/medium_font_size" + android:textSize="@dimen/small_font_size" android:maxLines="1" android:ellipsize="end" tools:text="The-Amazing-Spider-Man.cba" /> @@ -99,6 +99,7 @@ android:layout_height="wrap_content" android:layout_marginTop="4dp" style="@style/Signal.Text.Body" + android:textSize="@dimen/small_font_size" android:ellipsize="end" android:maxLines="2" tools:text="With great power comes great responsibility." diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java index ca3d10db17..385c0fa9ab 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -87,6 +87,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob; import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt; import org.thoughtcrime.securesms.loki.utilities.MentionUtilities; import org.thoughtcrime.securesms.loki.views.ProfilePictureView; import org.thoughtcrime.securesms.mms.GlideRequests; @@ -502,23 +503,23 @@ public class ConversationItem extends LinearLayout if (hasOnlyThumbnail(messageRecord)) { int topPadding = 0; if (groupSenderHolder.getVisibility() == VISIBLE) { - topPadding = (int)getResources().getDimension(R.dimen.medium_spacing); + topPadding = GeneralUtilitiesKt.toPx(12, getResources()); } int bottomPadding = 0; if (messageRecord.getBody().length() > 0) { - bodyTextLayoutParams.topMargin = (int)getResources().getDimension(R.dimen.medium_spacing); - bottomPadding = (int)getResources().getDimension(R.dimen.medium_spacing); + bodyTextLayoutParams.topMargin = GeneralUtilitiesKt.toPx(12, getResources()); + bottomPadding = GeneralUtilitiesKt.toPx(12, getResources()); } bodyBubble.setPadding(0, topPadding, 0, bottomPadding); } else { - bodyBubble.setPadding(0, (int)getResources().getDimension(R.dimen.medium_spacing), 0, (int)getResources().getDimension(R.dimen.medium_spacing)); + bodyBubble.setPadding(0, GeneralUtilitiesKt.toPx(12, getResources()), 0, GeneralUtilitiesKt.toPx(12, getResources())); } bodyText.setLayoutParams(bodyTextLayoutParams); LinearLayout.LayoutParams senderHolderLayoutParams = (LinearLayout.LayoutParams)groupSenderHolder.getLayoutParams(); if (groupSenderHolder.getVisibility() == VISIBLE && hasOnlyText(messageRecord)) { senderHolderLayoutParams.bottomMargin = (int)(getResources().getDisplayMetrics().density * 4); } else { - senderHolderLayoutParams.bottomMargin = (int)getResources().getDimension(R.dimen.medium_spacing); + senderHolderLayoutParams.bottomMargin = GeneralUtilitiesKt.toPx(12, getResources()); } groupSenderHolder.setLayoutParams(senderHolderLayoutParams); if (documentViewStub.resolved()) { From efbce3afa3f962102b8e5237881e820889b6ea17 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Fri, 4 Sep 2020 15:52:32 +1000 Subject: [PATCH 10/69] Fix inconsistent button styles --- res/layout-sw400dp/fragment_enter_chat_url.xml | 2 +- res/layout-sw400dp/fragment_enter_public_key.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/layout-sw400dp/fragment_enter_chat_url.xml b/res/layout-sw400dp/fragment_enter_chat_url.xml index 564580c481..f1a0feb4a0 100644 --- a/res/layout-sw400dp/fragment_enter_chat_url.xml +++ b/res/layout-sw400dp/fragment_enter_chat_url.xml @@ -23,7 +23,7 @@ android:layout_weight="1" />