Skip to content

Commit

Permalink
Add ability to insert GIFs from keyboard
Browse files Browse the repository at this point in the history
Closes vector-im/verticals-internal#21
  • Loading branch information
jonnyandrew committed Feb 28, 2023
1 parent 39d9591 commit f1f4eed
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 23 deletions.
1 change: 1 addition & 0 deletions changelog.d/8185.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Rich text editor] Add ability to insert GIFs from keyboard
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

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

import android.content.ClipData
import android.content.Context
import android.net.Uri
import android.os.Build
Expand All @@ -27,12 +26,12 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.view.OnReceiveContentListener
import androidx.core.view.ViewCompat
import androidx.core.view.inputmethod.EditorInfoCompat
import androidx.core.view.inputmethod.InputConnectionCompat
import im.vector.app.core.extensions.ooi
import im.vector.app.core.platform.SimpleTextWatcher
import im.vector.app.features.home.room.detail.composer.images.UriContentListener
import im.vector.app.features.html.PillImageSpan
import timber.log.Timber

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

val onReceiveContentListener = OnReceiveContentListener { _, payload ->
val split = payload.partition { item -> item.uri != null }
val uriContent = split.first
val remaining = split.second

if (uriContent != null) {
val clip: ClipData = uriContent.clip
for (i in 0 until clip.itemCount) {
val uri = clip.getItemAt(i).uri
// ... app-specific logic to handle the URI ...
callback?.onRichContentSelected(uri)
}
}
// Return anything that we didn't handle ourselves. This preserves the default platform
// behavior for text and anything else for which we are not implementing custom handling.
// Return anything that we didn't handle ourselves. This preserves the default platform
// behavior for text and anything else for which we are not implementing custom handling.
remaining
}

ViewCompat.setOnReceiveContentListener(this, mimeTypes, onReceiveContentListener)
ViewCompat.setOnReceiveContentListener(
this,
mimeTypes,
UriContentListener { callback?.onRichContentSelected(it) }
)

return ic
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.text.toSpannable
import androidx.core.view.ViewCompat
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
Expand All @@ -47,6 +48,7 @@ import im.vector.app.core.extensions.showKeyboard
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ComposerRichTextLayoutBinding
import im.vector.app.databinding.ViewRichTextMenuButtonBinding
import im.vector.app.features.home.room.detail.composer.images.UriContentListener
import io.element.android.wysiwyg.EditorEditText
import io.element.android.wysiwyg.inputhandlers.models.InlineFormat
import io.element.android.wysiwyg.inputhandlers.models.LinkAction
Expand Down Expand Up @@ -188,6 +190,16 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
views.plainTextComposerEditText.addTextChangedListener(
TextChangeListener({ callback?.onTextChanged(it) }, { updateTextFieldBorder(isFullScreen) })
)
ViewCompat.setOnReceiveContentListener(
views.richTextComposerEditText,
arrayOf("image/*"),
UriContentListener { callback?.onRichContentSelected(it) }
)
ViewCompat.setOnReceiveContentListener(
views.plainTextComposerEditText,
arrayOf("image/*"),
UriContentListener { callback?.onRichContentSelected(it) }
)

disallowParentInterceptTouchEvent(views.richTextComposerEditText)
disallowParentInterceptTouchEvent(views.plainTextComposerEditText)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.app.features.home.room.detail.composer.images

import android.content.ClipData
import android.net.Uri
import android.view.View
import androidx.core.view.ContentInfoCompat
import androidx.core.view.OnReceiveContentListener

class UriContentListener(
private val onContent: (uri: Uri) -> Unit
) : OnReceiveContentListener {
override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? {
val split = payload.partition { item -> item.uri != null }
val uriContent = split.first
val remaining = split.second

if (uriContent != null) {
val clip: ClipData = uriContent.clip
for (i in 0 until clip.itemCount) {
val uri = clip.getItemAt(i).uri
// ... app-specific logic to handle the URI ...
onContent(uri)
}
}
// Return anything that we didn't handle ourselves. This preserves the default platform
// behavior for text and anything else for which we are not implementing custom handling.
return remaining
}
}

0 comments on commit f1f4eed

Please sign in to comment.