SES-1352 - User and group names allowing multi-line strings (#1395)

* Fix WIP

* Resolved issue - pushing before cleanup & PR tomorrow morning

* Enforced single line for new closed group names

* Fixes #1394

* Final cleanup prior to PR

* Added code to restore a previous contact nickname if an empty one is given

* Added initial limits to nicknames and group names, both creation and display

* Minor adjustments

* Adjusted max nickname and group name to 35 chars as per Kee's instructions

* Fixed closed group edit text able to get too wide and cut off buttons

---------

Co-authored-by: = <=>
Co-authored-by: AL-Session <160798022+AL-Session@users.noreply.github.com>
Co-authored-by: Al Lansley <al@oxen.io>
This commit is contained in:
Al Lansley 2024-03-27 07:26:56 +11:00 committed by GitHub
parent 9e62e1eab4
commit 54d6c025b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 57 additions and 9 deletions

View File

@ -78,7 +78,7 @@ class CreateGroupFragment : Fragment() {
if (name.isEmpty()) { if (name.isEmpty()) {
return@setOnClickListener Toast.makeText(context, R.string.activity_create_closed_group_group_name_missing_error, Toast.LENGTH_LONG).show() return@setOnClickListener Toast.makeText(context, R.string.activity_create_closed_group_group_name_missing_error, Toast.LENGTH_LONG).show()
} }
if (name.length >= 30) { if (name.length > resources.getInteger(R.integer.max_group_and_community_name_length_chars)) {
return@setOnClickListener Toast.makeText(context, R.string.activity_create_closed_group_group_name_too_long_error, Toast.LENGTH_LONG).show() return@setOnClickListener Toast.makeText(context, R.string.activity_create_closed_group_group_name_too_long_error, Toast.LENGTH_LONG).show()
} }
val selectedMembers = adapter.selectedMembers val selectedMembers = adapter.selectedMembers

View File

@ -25,7 +25,6 @@ import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.IdPrefix
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.mms.GlideApp
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -34,6 +33,9 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() {
@Inject lateinit var threadDb: ThreadDatabase @Inject lateinit var threadDb: ThreadDatabase
private lateinit var binding: FragmentUserDetailsBottomSheetBinding private lateinit var binding: FragmentUserDetailsBottomSheetBinding
private var previousContactNickname: String = ""
companion object { companion object {
const val ARGUMENT_PUBLIC_KEY = "publicKey" const val ARGUMENT_PUBLIC_KEY = "publicKey"
const val ARGUMENT_THREAD_ID = "threadId" const val ARGUMENT_THREAD_ID = "threadId"
@ -130,9 +132,10 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() {
nameTextViewContainer.visibility = View.VISIBLE nameTextViewContainer.visibility = View.VISIBLE
nameEditTextContainer.visibility = View.INVISIBLE nameEditTextContainer.visibility = View.INVISIBLE
var newNickName: String? = null var newNickName: String? = null
if (nicknameEditText.text.isNotEmpty()) { if (nicknameEditText.text.isNotEmpty() && nicknameEditText.text.trim().length != 0) {
newNickName = nicknameEditText.text.toString() newNickName = nicknameEditText.text.toString()
} }
else { newNickName = previousContactNickname }
val publicKey = recipient.address.serialize() val publicKey = recipient.address.serialize()
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val contact = storage.getContactWithSessionID(publicKey) ?: Contact(publicKey) val contact = storage.getContactWithSessionID(publicKey) ?: Contact(publicKey)
@ -145,6 +148,9 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() {
fun showSoftKeyboard() { fun showSoftKeyboard() {
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(binding.nicknameEditText, 0) imm?.showSoftInput(binding.nicknameEditText, 0)
// Keep track of the original nickname to re-use if an empty / blank nickname is entered
previousContactNickname = binding.nameTextView.text.toString()
} }
fun hideSoftKeyboard() { fun hideSoftKeyboard() {

View File

@ -17,6 +17,7 @@ import android.view.ActionMode
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -203,6 +204,21 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
binding.displayNameEditText.selectAll() binding.displayNameEditText.selectAll()
binding.displayNameEditText.requestFocus() binding.displayNameEditText.requestFocus()
inputMethodManager.showSoftInput(binding.displayNameEditText, 0) inputMethodManager.showSoftInput(binding.displayNameEditText, 0)
// Save the updated display name when the user presses enter on the soft keyboard
binding.displayNameEditText.setOnEditorActionListener { v, actionId, event ->
when (actionId) {
// Note: IME_ACTION_DONE is how we've configured the soft keyboard to respond,
// while IME_ACTION_UNSPECIFIED is what triggers when we hit enter on a
// physical keyboard.
EditorInfo.IME_ACTION_DONE, EditorInfo.IME_ACTION_UNSPECIFIED -> {
saveDisplayName()
displayNameEditActionMode?.finish()
true
}
else -> false
}
}
} else { } else {
inputMethodManager.hideSoftInputFromWindow(binding.displayNameEditText.windowToken, 0) inputMethodManager.hideSoftInputFromWindow(binding.displayNameEditText.windowToken, 0)
} }

View File

@ -43,6 +43,8 @@
android:paddingBottom="0dp" android:paddingBottom="0dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:inputType="textCapWords" android:inputType="textCapWords"
android:maxLength="@integer/max_user_nickname_length_chars"
android:maxLines="1"
android:hint="@string/activity_display_name_edit_text_hint" /> android:hint="@string/activity_display_name_edit_text_hint" />
<View <View

View File

@ -43,6 +43,8 @@
android:paddingBottom="0dp" android:paddingBottom="0dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:inputType="textCapWords" android:inputType="textCapWords"
android:maxLength="@integer/max_user_nickname_length_chars"
android:maxLines="1"
android:hint="@string/activity_display_name_edit_text_hint" /> android:hint="@string/activity_display_name_edit_text_hint" />
<View <View

View File

@ -32,6 +32,7 @@
android:id="@+id/btnCancelGroupNameEdit" android:id="@+id/btnCancelGroupNameEdit"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginLeft="@dimen/medium_spacing"
android:contentDescription="@string/AccessibilityId_cancel_name_change" android:contentDescription="@string/AccessibilityId_cancel_name_change"
android:src="@drawable/ic_baseline_clear_24"/> android:src="@drawable/ic_baseline_clear_24"/>
@ -49,6 +50,7 @@
android:inputType="text" android:inputType="text"
android:singleLine="true" android:singleLine="true"
android:imeOptions="actionDone" android:imeOptions="actionDone"
android:maxLength="@integer/max_group_and_community_name_length_chars"
android:contentDescription="@string/AccessibilityId_group_name" android:contentDescription="@string/AccessibilityId_group_name"
android:hint="@string/activity_edit_closed_group_edit_text_hint" /> android:hint="@string/activity_edit_closed_group_edit_text_hint" />
@ -57,6 +59,7 @@
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginRight="@dimen/medium_spacing"
android:contentDescription="@string/AccessibilityId_accept_name_change" android:contentDescription="@string/AccessibilityId_accept_name_change"
android:src="@drawable/ic_baseline_done_24"/> android:src="@drawable/ic_baseline_done_24"/>

View File

@ -47,7 +47,11 @@
android:paddingTop="12dp" android:paddingTop="12dp"
android:paddingBottom="12dp" android:paddingBottom="12dp"
android:visibility="invisible" android:visibility="invisible"
android:hint="@string/activity_settings_display_name_edit_text_hint" /> android:hint="@string/activity_settings_display_name_edit_text_hint"
android:imeOptions="actionDone"
android:inputType="textCapWords"
android:maxLength="@integer/max_user_nickname_length_chars"
android:maxLines="1" />
<TextView <TextView
android:id="@+id/btnGroupNameDisplay" android:id="@+id/btnGroupNameDisplay"
@ -57,6 +61,7 @@
android:contentDescription="@string/AccessibilityId_username" android:contentDescription="@string/AccessibilityId_username"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="@dimen/very_large_font_size" android:textSize="@dimen/very_large_font_size"
android:maxLength="@integer/max_user_nickname_length_chars"
android:textStyle="bold" /> android:textStyle="bold" />
</RelativeLayout> </RelativeLayout>

View File

@ -62,10 +62,14 @@
android:layout_marginBottom="@dimen/medium_spacing" android:layout_marginBottom="@dimen/medium_spacing"
android:contentDescription="@string/AccessibilityId_group_name_input" android:contentDescription="@string/AccessibilityId_group_name_input"
android:hint="@string/activity_create_closed_group_edit_text_hint" android:hint="@string/activity_create_closed_group_edit_text_hint"
android:maxLength="30" android:imeOptions="actionDone"
android:inputType="textCapWords"
android:maxLength="@integer/max_group_and_community_name_length_chars"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" /> app:layout_constraintTop_toBottomOf="@id/titleText"
tools:ignore="ContentDescription" />
<org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView <org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
android:id="@+id/contactSearch" android:id="@+id/contactSearch"

View File

@ -29,6 +29,8 @@
android:id="@+id/nameTextViewContainer" android:id="@+id/nameTextViewContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="@dimen/medium_spacing"
android:paddingEnd="@dimen/medium_spacing"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_centerInParent="true" android:layout_centerInParent="true"
@ -42,6 +44,7 @@
android:id="@+id/nameTextView" android:id="@+id/nameTextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="@dimen/small_spacing" android:layout_marginStart="@dimen/small_spacing"
android:layout_marginEnd="@dimen/small_spacing" android:layout_marginEnd="@dimen/small_spacing"
@ -57,6 +60,7 @@
android:layout_height="22dp" android:layout_height="22dp"
android:contentDescription="@string/AccessibilityId_edit_user_nickname" android:contentDescription="@string/AccessibilityId_edit_user_nickname"
android:paddingTop="2dp" android:paddingTop="2dp"
android:layout_marginEnd="20dp"
android:src="@drawable/ic_baseline_edit_24" /> android:src="@drawable/ic_baseline_edit_24" />
</LinearLayout> </LinearLayout>
@ -73,6 +77,7 @@
android:id="@+id/cancelNicknameEditingButton" android:id="@+id/cancelNicknameEditingButton"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginLeft="@dimen/large_spacing"
android:contentDescription="@string/AccessibilityId_cancel" android:contentDescription="@string/AccessibilityId_cancel"
android:src="@drawable/ic_baseline_clear_24" /> android:src="@drawable/ic_baseline_clear_24" />
@ -82,12 +87,12 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginHorizontal="@dimen/small_spacing"
android:contentDescription="@string/AccessibilityId_username" android:contentDescription="@string/AccessibilityId_username"
android:textAlignment="center" android:textAlignment="center"
android:paddingVertical="12dp" android:paddingVertical="12dp"
android:inputType="text" android:inputType="text"
android:singleLine="true" android:maxLength="@integer/max_user_nickname_length_chars"
android:maxLines="1"
android:imeOptions="actionDone" android:imeOptions="actionDone"
android:textColorHint="?android:textColorSecondary" android:textColorHint="?android:textColorSecondary"
android:hint="@string/fragment_user_details_bottom_sheet_edit_text_hint" /> android:hint="@string/fragment_user_details_bottom_sheet_edit_text_hint" />
@ -96,6 +101,7 @@
android:id="@+id/saveNicknameButton" android:id="@+id/saveNicknameButton"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginRight="@dimen/large_spacing"
android:contentDescription="@string/AccessibilityId_apply" android:contentDescription="@string/AccessibilityId_apply"
android:src="@drawable/ic_baseline_done_24" /> android:src="@drawable/ic_baseline_done_24" />

View File

@ -25,6 +25,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/medium_spacing" android:layout_marginStart="@dimen/medium_spacing"
android:maxLength="@integer/max_user_nickname_length_chars"
android:maxLines="1" android:maxLines="1"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:ellipsize="end" android:ellipsize="end"

View File

@ -165,7 +165,7 @@
android:maxLines="1" android:maxLines="1"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="@dimen/medium_font_size" android:textSize="@dimen/medium_font_size"
tools:text="Sorry, gotta go fight crime again" /> tools:text="Sorry, gotta go fight crime again - and more text to make it ellipsize" />
<include layout="@layout/view_typing_indicator" <include layout="@layout/view_typing_indicator"
android:id="@+id/typingIndicatorView" android:id="@+id/typingIndicatorView"

View File

@ -6,4 +6,7 @@
<integer name="reaction_scrubber_reveal_offset">100</integer> <integer name="reaction_scrubber_reveal_offset">100</integer>
<integer name="reaction_scrubber_hide_duration">150</integer> <integer name="reaction_scrubber_hide_duration">150</integer>
<integer name="reaction_scrubber_emoji_reveal_duration_start_delay_factor">10</integer> <integer name="reaction_scrubber_emoji_reveal_duration_start_delay_factor">10</integer>
<integer name="max_user_nickname_length_chars">35</integer>
<integer name="max_group_and_community_name_length_chars">35</integer>
</resources> </resources>