Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions app/src/main/java/com/nextcloud/talk/chat/MessageInputFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

package com.nextcloud.talk.chat

import android.content.res.Resources
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Build
Expand All @@ -16,6 +15,7 @@ import android.os.CountDownTimer
import android.os.SystemClock
import android.text.Editable
import android.text.InputFilter
import android.text.Spanned
import android.text.TextUtils
import android.text.TextWatcher
import android.util.Log
Expand Down Expand Up @@ -85,7 +85,7 @@ import kotlinx.coroutines.launch
import java.util.Objects
import javax.inject.Inject

@Suppress("LongParameterList", "TooManyFunctions")
@Suppress("LongParameterList", "TooManyFunctions", "LargeClass")
@AutoInjector(NextcloudTalkApplication::class)
class MessageInputFragment : Fragment() {

Expand All @@ -108,6 +108,19 @@ class MessageInputFragment : Fragment() {
private const val CONNECTION_ESTABLISHED_ANIM_DURATION: Long = 3000
private const val FULLY_OPAQUE: Float = 1.0f
private const val FULLY_TRANSPARENT: Float = 0.0f

/**
* Note: Start index guaranteed >= 0 if correct, -1 if error
* @return `Pair(start index + 1, end index)
*/
private fun String.getStartAndEndIndexOf(substring: String): Pair<Int, Int> {
val index = this.indexOf(substring)
if (index < 0) return Pair(-1, -1)

val start = kotlin.math.max(0, index + 1)
val end = start + substring.length
return Pair(start, end)
}
}

@Inject
Expand Down Expand Up @@ -156,10 +169,6 @@ class MessageInputFragment : Fragment() {
saveState()
}

override fun onResume() {
super.onResume()
}

override fun onDestroyView() {
super.onDestroyView()
if (mentionAutocomplete != null && mentionAutocomplete!!.isPopupShowing) {
Expand Down Expand Up @@ -348,35 +357,44 @@ class MessageInputFragment : Fragment() {

if (s.length >= lengthFilter) {
binding.fragmentMessageInputView.inputEditText?.error = String.format(
Objects.requireNonNull<Resources>(resources).getString(R.string.nc_limit_hit),
Objects.requireNonNull(resources).getString(R.string.nc_limit_hit),
lengthFilter.toString()
)
} else {
binding.fragmentMessageInputView.inputEditText?.error = null
}

val editable = binding.fragmentMessageInputView.inputEditText?.editableText
if (editable == null || binding.fragmentMessageInputView.inputEditText == null) return

val mentionSpans = editable.getSpans(
0,
binding.fragmentMessageInputView.inputEditText!!.length(),
Spans.MentionChipSpan::class.java
)
var mentionSpan: Spans.MentionChipSpan
for (i in mentionSpans.indices) {
mentionSpan = mentionSpans[i]

val spStart = editable.getSpanStart(mentionSpan)
val spEnd = editable.getSpanEnd(mentionSpan)
val spanRangeStr = editable.subSequence(spStart, spEnd).toString().trim { it <= ' ' }
val error = spanRangeStr.length > mentionSpan.label.length

if (start in spStart..<spEnd && spanRangeStr != mentionSpan.label) {
editable.removeSpan(mentionSpan)
}

if (editable != null && binding.fragmentMessageInputView.inputEditText != null) {
val mentionSpans = editable.getSpans(
0,
binding.fragmentMessageInputView.inputEditText!!.length(),
Spans.MentionChipSpan::class.java
)
var mentionSpan: Spans.MentionChipSpan
for (i in mentionSpans.indices) {
mentionSpan = mentionSpans[i]
if (start >= editable.getSpanStart(mentionSpan) &&
start < editable.getSpanEnd(mentionSpan)
) {
if (editable.subSequence(
editable.getSpanStart(mentionSpan),
editable.getSpanEnd(mentionSpan)
).toString().trim { it <= ' ' } != mentionSpan.label
) {
editable.removeSpan(mentionSpan)
}
// workaround, not a proper fix for issue #4642
if (error) {
val pair = spanRangeStr.getStartAndEndIndexOf(mentionSpan.label.toString())
if (pair.first < 0) {
Log.e(TAG, "Mention Span not found in editable: Not reinserted")
return
}

editable.setSpan(mentionSpan, pair.first, pair.second, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
Log.e(TAG, "Reinserted Span in editable at Start: ${pair.first} End: ${pair.second}")
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/nextcloud/talk/utils/CharPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@

import android.text.Spannable;
import android.text.Spanned;
import androidx.annotation.Nullable;

import com.otaliastudios.autocomplete.AutocompletePolicy;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import androidx.annotation.Nullable;

public class CharPolicy implements AutocompletePolicy {

private final char character;
Expand Down
Loading