|
|
@ -16,10 +16,13 @@ |
|
|
|
|
|
|
|
|
|
|
|
package io.element.android.libraries.textcomposer.components.markdown |
|
|
|
package io.element.android.libraries.textcomposer.components.markdown |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import android.content.ClipData |
|
|
|
import android.graphics.Color |
|
|
|
import android.graphics.Color |
|
|
|
|
|
|
|
import android.net.Uri |
|
|
|
import android.text.Editable |
|
|
|
import android.text.Editable |
|
|
|
import android.text.InputType |
|
|
|
import android.text.InputType |
|
|
|
import android.text.Selection |
|
|
|
import android.text.Selection |
|
|
|
|
|
|
|
import android.view.View |
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth |
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth |
|
|
|
import androidx.compose.foundation.layout.padding |
|
|
|
import androidx.compose.foundation.layout.padding |
|
|
|
import androidx.compose.runtime.Composable |
|
|
|
import androidx.compose.runtime.Composable |
|
|
@ -27,6 +30,9 @@ import androidx.compose.ui.Modifier |
|
|
|
import androidx.compose.ui.unit.dp |
|
|
|
import androidx.compose.ui.unit.dp |
|
|
|
import androidx.compose.ui.viewinterop.AndroidView |
|
|
|
import androidx.compose.ui.viewinterop.AndroidView |
|
|
|
import androidx.core.text.getSpans |
|
|
|
import androidx.core.text.getSpans |
|
|
|
|
|
|
|
import androidx.core.view.ContentInfoCompat |
|
|
|
|
|
|
|
import androidx.core.view.OnReceiveContentListener |
|
|
|
|
|
|
|
import androidx.core.view.ViewCompat |
|
|
|
import androidx.core.view.setPadding |
|
|
|
import androidx.core.view.setPadding |
|
|
|
import androidx.core.widget.addTextChangedListener |
|
|
|
import androidx.core.widget.addTextChangedListener |
|
|
|
import io.element.android.libraries.designsystem.preview.ElementPreview |
|
|
|
import io.element.android.libraries.designsystem.preview.ElementPreview |
|
|
@ -48,8 +54,33 @@ fun MarkdownTextInput( |
|
|
|
onTyping: (Boolean) -> Unit, |
|
|
|
onTyping: (Boolean) -> Unit, |
|
|
|
onSuggestionReceived: (Suggestion?) -> Unit, |
|
|
|
onSuggestionReceived: (Suggestion?) -> Unit, |
|
|
|
richTextEditorStyle: RichTextEditorStyle, |
|
|
|
richTextEditorStyle: RichTextEditorStyle, |
|
|
|
|
|
|
|
onRichContentSelected: ((Uri) -> Unit)?, |
|
|
|
) { |
|
|
|
) { |
|
|
|
val canUpdateState = !subcomposing |
|
|
|
val canUpdateState = !subcomposing |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Copied from io.element.android.wysiwyg.internal.utils.UriContentListener |
|
|
|
|
|
|
|
class ReceiveUriContentListener( |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AndroidView( |
|
|
|
AndroidView( |
|
|
|
modifier = Modifier |
|
|
|
modifier = Modifier |
|
|
|
.padding(top = 6.dp, bottom = 6.dp) |
|
|
|
.padding(top = 6.dp, bottom = 6.dp) |
|
|
@ -82,6 +113,13 @@ fun MarkdownTextInput( |
|
|
|
state.currentMentionSuggestion = editableText.checkSuggestionNeeded() |
|
|
|
state.currentMentionSuggestion = editableText.checkSuggestionNeeded() |
|
|
|
onSuggestionReceived(state.currentMentionSuggestion) |
|
|
|
onSuggestionReceived(state.currentMentionSuggestion) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (onRichContentSelected != null) { |
|
|
|
|
|
|
|
ViewCompat.setOnReceiveContentListener( |
|
|
|
|
|
|
|
this, |
|
|
|
|
|
|
|
arrayOf("image/*"), |
|
|
|
|
|
|
|
ReceiveUriContentListener { onRichContentSelected(it) } |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
state.requestFocusAction = { this.requestFocus() } |
|
|
|
state.requestFocusAction = { this.requestFocus() } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -152,6 +190,7 @@ internal fun MarkdownTextInputPreview() { |
|
|
|
onTyping = {}, |
|
|
|
onTyping = {}, |
|
|
|
onSuggestionReceived = {}, |
|
|
|
onSuggestionReceived = {}, |
|
|
|
richTextEditorStyle = style, |
|
|
|
richTextEditorStyle = style, |
|
|
|
|
|
|
|
onRichContentSelected = {}, |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|