Skip to content

Commit f1f4eed

Browse files
committed
Add ability to insert GIFs from keyboard
Closes vector-im/verticals-internal#21
1 parent 39d9591 commit f1f4eed

File tree

4 files changed

+64
-23
lines changed

4 files changed

+64
-23
lines changed

changelog.d/8185.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Rich text editor] Add ability to insert GIFs from keyboard

vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt

+6-23
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package im.vector.app.features.home.room.detail.composer
1919

20-
import android.content.ClipData
2120
import android.content.Context
2221
import android.net.Uri
2322
import android.os.Build
@@ -27,12 +26,12 @@ import android.view.inputmethod.EditorInfo
2726
import android.view.inputmethod.InputConnection
2827
import androidx.annotation.RequiresApi
2928
import androidx.appcompat.widget.AppCompatEditText
30-
import androidx.core.view.OnReceiveContentListener
3129
import androidx.core.view.ViewCompat
3230
import androidx.core.view.inputmethod.EditorInfoCompat
3331
import androidx.core.view.inputmethod.InputConnectionCompat
3432
import im.vector.app.core.extensions.ooi
3533
import im.vector.app.core.platform.SimpleTextWatcher
34+
import im.vector.app.features.home.room.detail.composer.images.UriContentListener
3635
import im.vector.app.features.html.PillImageSpan
3736
import timber.log.Timber
3837

@@ -56,27 +55,11 @@ class ComposerEditText @JvmOverloads constructor(
5655
EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes)
5756
ic = InputConnectionCompat.createWrapper(this, ic, editorInfo)
5857

59-
val onReceiveContentListener = OnReceiveContentListener { _, payload ->
60-
val split = payload.partition { item -> item.uri != null }
61-
val uriContent = split.first
62-
val remaining = split.second
63-
64-
if (uriContent != null) {
65-
val clip: ClipData = uriContent.clip
66-
for (i in 0 until clip.itemCount) {
67-
val uri = clip.getItemAt(i).uri
68-
// ... app-specific logic to handle the URI ...
69-
callback?.onRichContentSelected(uri)
70-
}
71-
}
72-
// Return anything that we didn't handle ourselves. This preserves the default platform
73-
// behavior for text and anything else for which we are not implementing custom handling.
74-
// Return anything that we didn't handle ourselves. This preserves the default platform
75-
// behavior for text and anything else for which we are not implementing custom handling.
76-
remaining
77-
}
78-
79-
ViewCompat.setOnReceiveContentListener(this, mimeTypes, onReceiveContentListener)
58+
ViewCompat.setOnReceiveContentListener(
59+
this,
60+
mimeTypes,
61+
UriContentListener { callback?.onRichContentSelected(it) }
62+
)
8063

8164
return ic
8265
}

vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt

+12
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import androidx.annotation.DrawableRes
3636
import androidx.annotation.StringRes
3737
import androidx.constraintlayout.widget.ConstraintSet
3838
import androidx.core.text.toSpannable
39+
import androidx.core.view.ViewCompat
3940
import androidx.core.view.isGone
4041
import androidx.core.view.isInvisible
4142
import androidx.core.view.isVisible
@@ -47,6 +48,7 @@ import im.vector.app.core.extensions.showKeyboard
4748
import im.vector.app.core.utils.DimensionConverter
4849
import im.vector.app.databinding.ComposerRichTextLayoutBinding
4950
import im.vector.app.databinding.ViewRichTextMenuButtonBinding
51+
import im.vector.app.features.home.room.detail.composer.images.UriContentListener
5052
import io.element.android.wysiwyg.EditorEditText
5153
import io.element.android.wysiwyg.inputhandlers.models.InlineFormat
5254
import io.element.android.wysiwyg.inputhandlers.models.LinkAction
@@ -188,6 +190,16 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
188190
views.plainTextComposerEditText.addTextChangedListener(
189191
TextChangeListener({ callback?.onTextChanged(it) }, { updateTextFieldBorder(isFullScreen) })
190192
)
193+
ViewCompat.setOnReceiveContentListener(
194+
views.richTextComposerEditText,
195+
arrayOf("image/*"),
196+
UriContentListener { callback?.onRichContentSelected(it) }
197+
)
198+
ViewCompat.setOnReceiveContentListener(
199+
views.plainTextComposerEditText,
200+
arrayOf("image/*"),
201+
UriContentListener { callback?.onRichContentSelected(it) }
202+
)
191203

192204
disallowParentInterceptTouchEvent(views.richTextComposerEditText)
193205
disallowParentInterceptTouchEvent(views.plainTextComposerEditText)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2023 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package im.vector.app.features.home.room.detail.composer.images
18+
19+
import android.content.ClipData
20+
import android.net.Uri
21+
import android.view.View
22+
import androidx.core.view.ContentInfoCompat
23+
import androidx.core.view.OnReceiveContentListener
24+
25+
class UriContentListener(
26+
private val onContent: (uri: Uri) -> Unit
27+
) : OnReceiveContentListener {
28+
override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? {
29+
val split = payload.partition { item -> item.uri != null }
30+
val uriContent = split.first
31+
val remaining = split.second
32+
33+
if (uriContent != null) {
34+
val clip: ClipData = uriContent.clip
35+
for (i in 0 until clip.itemCount) {
36+
val uri = clip.getItemAt(i).uri
37+
// ... app-specific logic to handle the URI ...
38+
onContent(uri)
39+
}
40+
}
41+
// Return anything that we didn't handle ourselves. This preserves the default platform
42+
// behavior for text and anything else for which we are not implementing custom handling.
43+
return remaining
44+
}
45+
}

0 commit comments

Comments
 (0)