@@ -6,14 +6,10 @@ import android.net.Uri
66import android.util.AttributeSet
77import android.view.inputmethod.EditorInfo
88import android.view.inputmethod.InputConnection
9- import android.widget.RelativeLayout
109import androidx.appcompat.widget.AppCompatEditText
1110import androidx.core.view.inputmethod.EditorInfoCompat
1211import androidx.core.view.inputmethod.InputConnectionCompat
13- import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities
1412import org.thoughtcrime.securesms.util.toPx
15- import kotlin.math.max
16- import kotlin.math.min
1713import kotlin.math.roundToInt
1814
1915class InputBarEditText : AppCompatEditText {
@@ -22,21 +18,42 @@ class InputBarEditText : AppCompatEditText {
2218
2319 var allowMultimediaInput: Boolean = true
2420
25-
2621 constructor (context: Context ) : super (context)
2722 constructor (context: Context , attrs: AttributeSet ) : super (context, attrs)
2823 constructor (context: Context , attrs: AttributeSet , defStyleAttr: Int ) : super (context, attrs, defStyleAttr)
2924
3025 override fun onTextChanged (text : CharSequence , start : Int , lengthBefore : Int , lengthAfter : Int ) {
3126 super .onTextChanged(text, start, lengthBefore, lengthAfter)
3227 delegate?.inputBarEditTextContentChanged(text)
28+
29+ // - A "chunk" got inserted (lengthAfter >= 3)
30+ // - If it is large enough, treat it as paste. We do this because some IME's clipboard history
31+ // will not be treated as a "paste" but instead just a normal text insertion
32+ if (lengthAfter >= 3 ) { // catch most real paste
33+ val inserted = safeSubSequence(text, start, start + lengthAfter)
34+ if (! inserted.isNullOrEmpty()) {
35+ // Bulk insert will mostly come from IME that supports clipboard history
36+ val isBulkInsert = inserted.length >= 5 // small enough to catch URIs
37+
38+ if (isBulkInsert) {
39+ delegate?.onPaste()
40+ }
41+ }
42+ }
43+
3344 // Calculate the width manually to get it right even before layout has happened (i.e.
3445 // when restoring a draft). The 64 DP is the horizontal margin around the input bar
3546 // edit text.
3647 val width = (screenWidth - 2 * toPx(64.0f , resources)).roundToInt()
3748 if (width < 0 ) { return } // screenWidth initially evaluates to 0
3849 }
3950
51+ // Small helper to avoid IndexOutOfBounds on weird IME behavior
52+ private fun safeSubSequence (text : CharSequence , start : Int , end : Int ): String? {
53+ if (start < 0 || end > text.length || start >= end) return null
54+ return text.subSequence(start, end).toString()
55+ }
56+
4057 override fun onCreateInputConnection (editorInfo : EditorInfo ): InputConnection ? {
4158 val ic = super .onCreateInputConnection(editorInfo) ? : return null
4259 EditorInfoCompat .setContentMimeTypes(editorInfo,
@@ -62,12 +79,15 @@ class InputBarEditText : AppCompatEditText {
6279
6380 true // return true if succeeded
6481 }
82+
83+
84+
6585 return InputConnectionCompat .createWrapper(ic, editorInfo, callback)
6686 }
67-
6887}
6988
7089interface InputBarEditTextDelegate {
7190 fun inputBarEditTextContentChanged (text : CharSequence )
7291 fun commitInputContent (contentUri : Uri )
92+ fun onPaste ()
7393}
0 commit comments