Skip to content
Merged
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
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,11 @@ dependencies {
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("com.google.android.material:material:1.14.0")
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
implementation("com.vanniktech:emoji-google:0.23.0")
implementation("androidx.emoji2:emoji2:$emojiVersion")
implementation("androidx.emoji2:emoji2-bundled:$emojiVersion")
implementation("androidx.emoji2:emoji2-views:$emojiVersion")
implementation("androidx.emoji2:emoji2-views-helper:$emojiVersion")
implementation("androidx.emoji2:emoji2-emojipicker:$emojiVersion")
implementation("org.michaelevans.colorart:library:0.0.3")
implementation("androidx.work:work-runtime:$workVersion")
implementation("androidx.work:work-rxjava2:$workVersion")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ import com.nextcloud.talk.utils.NotificationUtils
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
import com.nextcloud.talk.utils.database.user.UserModule
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider
import de.cotech.hw.SecurityKeyManager
import de.cotech.hw.SecurityKeyManagerConfig
import io.reactivex.exceptions.UndeliverableException
Expand Down Expand Up @@ -238,8 +236,6 @@ class NextcloudTalkApplication :
config.setReplaceAll(true)
val emojiCompat = EmojiCompat.init(config)

EmojiManager.install(GoogleEmojiProvider())

NotificationUtils.registerNotificationChannels(applicationContext, appPreferences)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.emoji2.widget.EmojiTextView
import com.nextcloud.talk.R
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.vanniktech.emoji.EmojiTextView

class ReactionAnimator(
val context: Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import android.text.Spanned;
import android.widget.EditText;

import androidx.emoji2.text.EmojiCompat;
import androidx.emoji2.text.EmojiSpan;

import com.nextcloud.talk.R;
import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.models.json.mention.Mention;
Expand All @@ -20,9 +23,10 @@
import com.nextcloud.talk.utils.CharPolicy;
import com.nextcloud.talk.utils.text.Spans;
import com.otaliastudios.autocomplete.AutocompleteCallback;
import com.vanniktech.emoji.EmojiRange;
import com.vanniktech.emoji.Emojis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import kotlin.OptIn;
Expand Down Expand Up @@ -54,8 +58,21 @@ public boolean onPopupItemClicked(Editable editable, Mention item) {
String replacement = item.getLabel();

StringBuilder replacementStringBuilder = new StringBuilder(Objects.requireNonNull(item.getLabel()));
for (EmojiRange emojiRange : Emojis.emojis(replacement)) {
replacementStringBuilder.delete(emojiRange.range.getStart(), emojiRange.range.getEndInclusive());
final EmojiCompat emojiCompat = EmojiCompat.get();
if (emojiCompat.getLoadState() == EmojiCompat.LOAD_STATE_SUCCEEDED) {
final CharSequence processed = emojiCompat.process(replacement);
if (processed instanceof Spanned) {
final Spanned spannedReplacement = (Spanned) processed;
final EmojiSpan[] emojiSpans =
spannedReplacement.getSpans(0, spannedReplacement.length(), EmojiSpan.class);
final List<EmojiSpan> sortedSpans = new ArrayList<>(Arrays.asList(emojiSpans));
sortedSpans.sort((a, b) -> spannedReplacement.getSpanStart(b) - spannedReplacement.getSpanStart(a));
for (EmojiSpan emojiSpan : sortedSpans) {
replacementStringBuilder.delete(
spannedReplacement.getSpanStart(emojiSpan),
spannedReplacement.getSpanEnd(emojiSpan));
}
}
}

String charSequence = " ";
Expand Down
74 changes: 0 additions & 74 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.Context
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.os.Build
Expand All @@ -30,7 +29,6 @@ import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.animation.Animation.AnimationListener
import android.view.animation.LinearInterpolator
import android.view.inputmethod.InputMethodManager
import android.widget.Chronometer
import android.widget.ImageButton
import android.widget.ImageView
Expand All @@ -40,7 +38,6 @@ import android.widget.RelativeLayout
import android.widget.SeekBar
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
Expand Down Expand Up @@ -92,7 +89,6 @@ import com.nextcloud.talk.utils.database.user.CurrentUserProviderOld
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.text.Spans
import com.otaliastudios.autocomplete.Autocomplete
import com.vanniktech.emoji.EmojiPopup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
Expand Down Expand Up @@ -129,9 +125,6 @@ class MessageInputFragment : Fragment() {
private var typedWhileTypingTimerIsRunning: Boolean = false
private var typingTimer: CountDownTimer? = null
private lateinit var chatActivity: ChatActivity
private var emojiPopup: EmojiPopup? = null
private var isEmojiPopupOpen = false
private var restoreKeyboardOnEmojiDismiss = false
private var mentionAutocomplete: Autocomplete<*>? = null
private var xcounter = 0f
private var ycounter = 0f
Expand Down Expand Up @@ -163,10 +156,6 @@ class MessageInputFragment : Fragment() {
}

override fun onDestroyView() {
restoreKeyboardOnEmojiDismiss = false
emojiPopup?.dismiss()
emojiPopup = null
isEmojiPopupOpen = false
super.onDestroyView()
if (mentionAutocomplete != null && mentionAutocomplete!!.isPopupShowing) {
mentionAutocomplete?.dismissPopup()
Expand All @@ -193,7 +182,6 @@ class MessageInputFragment : Fragment() {
when (state) {
is ChatViewModel.GetCapabilitiesUpdateState -> {
initMessageInputView(state.spreedCapabilities)
initSmileyKeyboardToggler()
setupMentionAutocomplete()
initVoiceRecordButton()
initThreadHandling()
Expand All @@ -202,7 +190,6 @@ class MessageInputFragment : Fragment() {

is ChatViewModel.GetCapabilitiesInitialLoadState -> {
initMessageInputView(state.spreedCapabilities)
initSmileyKeyboardToggler()
setupMentionAutocomplete()
initVoiceRecordButton()
initThreadHandling()
Expand Down Expand Up @@ -827,8 +814,6 @@ class MessageInputFragment : Fragment() {

private fun showRecordAudioUi(show: Boolean) {
if (show) {
restoreKeyboardOnEmojiDismiss = false
emojiPopup?.dismiss()
val animation: Animation = AlphaAnimation(FULLY_OPAQUE, FULLY_TRANSPARENT)
animation.duration = ANIMATION_DURATION
animation.interpolator = LinearInterpolator()
Expand All @@ -841,7 +826,6 @@ class MessageInputFragment : Fragment() {
binding.fragmentMessageInputView.audioRecordDuration.visibility = View.VISIBLE
binding.fragmentMessageInputView.slideToCancelDescription.visibility = View.VISIBLE
binding.fragmentMessageInputView.attachmentButton.visibility = View.GONE
binding.fragmentMessageInputView.smileyButton.visibility = View.GONE
binding.fragmentMessageInputView.messageInput.visibility = View.GONE
binding.fragmentMessageInputView.messageInput.hint = ""
binding.fragmentMessageInputView.scheduledMessagesButton.visibility = View.GONE
Expand All @@ -853,70 +837,12 @@ class MessageInputFragment : Fragment() {
binding.fragmentMessageInputView.audioRecordDuration.visibility = View.GONE
binding.fragmentMessageInputView.slideToCancelDescription.visibility = View.GONE
binding.fragmentMessageInputView.attachmentButton.visibility = View.VISIBLE
binding.fragmentMessageInputView.smileyButton.visibility = View.VISIBLE
binding.fragmentMessageInputView.messageInput.visibility = View.VISIBLE
binding.fragmentMessageInputView.messageInput.hint =
requireContext().resources?.getString(R.string.nc_hint_enter_a_message)
}
}

private fun updateSmileyButtonIcon() {
val icon = if (isEmojiPopupOpen) {
R.drawable.ic_baseline_keyboard_24
} else {
R.drawable.ic_insert_emoticon_black_24dp
}
val drawable = ContextCompat.getDrawable(requireContext(), icon)
binding.fragmentMessageInputView.smileyButton.setImageDrawable(drawable)
}

private fun showKeyboard() {
val editText = binding.fragmentMessageInputView.inputEditText
editText.requestFocus()
val inputMethodManager =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
inputMethodManager?.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}

private fun initSmileyKeyboardToggler() {
val inputEditText = binding.fragmentMessageInputView.inputEditText
if (emojiPopup == null) {
emojiPopup = EmojiPopup(
rootView = binding.root,
editText = inputEditText,
theming = viewThemeUtils.talk.getEmojiTheming(requireContext()),
onEmojiPopupShownListener = {
isEmojiPopupOpen = true
updateSmileyButtonIcon()
},
onEmojiPopupDismissListener = {
isEmojiPopupOpen = false
updateSmileyButtonIcon()
if (restoreKeyboardOnEmojiDismiss) {
restoreKeyboardOnEmojiDismiss = false
showKeyboard()
}
},
onEmojiClickListener = {
inputEditText.editableText?.append(" ")
}
)
}

updateSmileyButtonIcon()

binding.fragmentMessageInputView.smileyButton.setOnClickListener {
if (isEmojiPopupOpen) {
restoreKeyboardOnEmojiDismiss = true
emojiPopup?.dismiss()
} else {
restoreKeyboardOnEmojiDismiss = false
inputEditText.requestFocus()
emojiPopup?.toggle()
}
}
}

private fun replyToMessage(quotedMessageText: String?, quotedActorDisplayName: String?, quotedImageUrl: String?) {
Log.d(TAG, "Reply")
val view = binding.fragmentMessageInputView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
Expand All @@ -68,7 +67,6 @@ import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
Expand All @@ -83,6 +81,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.widget.addTextChangedListener
import androidx.emoji2.widget.EmojiEditText
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import autodagger.AutoInjector
Expand All @@ -107,15 +106,12 @@ import com.nextcloud.talk.ui.chat.LocalShowThreadButton
import com.nextcloud.talk.ui.chat.formatTime
import com.nextcloud.talk.ui.theme.LocalMessageUtils
import com.nextcloud.talk.ui.theme.LocalViewThemeUtils
import com.nextcloud.talk.ui.theme.emojiTheming
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateConstants
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_THREAD_ID
import com.vanniktech.emoji.EmojiEditText
import com.vanniktech.emoji.EmojiPopup
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import java.time.Instant
Expand Down Expand Up @@ -808,24 +804,14 @@ class ScheduledMessagesActivity : BaseActivity() {
onCancel: () -> Unit,
onSend: () -> Unit
) {
val rootView = LocalView.current
val keyboardController = LocalSoftwareKeyboardController.current
val theming = emojiTheming()

val emojiEditTextRef = remember { mutableStateOf<EmojiEditText?>(null) }
var emojiPopup by remember { mutableStateOf<EmojiPopup?>(null) }
var isEmojiOpen by remember { mutableStateOf(false) }

val canSend =
editValue.text.isNotBlank() &&
editValue.text.trim() != originalText.trim()

DisposableEffect(rootView) {
onDispose {
emojiPopup?.dismiss()
}
}

Surface(tonalElevation = 2.dp, modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(12.dp)) {
Row(
Expand All @@ -844,7 +830,6 @@ class ScheduledMessagesActivity : BaseActivity() {
modifier = Modifier.weight(1f)
)
IconButton(onClick = {
emojiPopup?.dismiss()
keyboardController?.hide()
onCancel()
}) {
Expand All @@ -867,37 +852,6 @@ class ScheduledMessagesActivity : BaseActivity() {
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = {
val editText = emojiEditTextRef.value ?: return@IconButton

if (emojiPopup == null) {
emojiPopup = EmojiPopup(
rootView = rootView,
editText = editText,
theming = theming,
onEmojiPopupShownListener = {
isEmojiOpen = true
},
onEmojiPopupDismissListener = {
isEmojiOpen = false
keyboardController?.show()
}
)
}

emojiPopup?.toggle()
}) {
Icon(
imageVector = if (isEmojiOpen) {
ImageVector.vectorResource(R.drawable.ic_baseline_keyboard_24)
} else {
ImageVector.vectorResource(R.drawable.ic_insert_emoticon_black_24dp)
},
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}

AndroidView(
modifier = Modifier
.weight(1f)
Expand Down Expand Up @@ -930,7 +884,6 @@ class ScheduledMessagesActivity : BaseActivity() {
onClick = {
if (!canSend) return@IconButton
emojiEditTextRef.value?.clearFocus()
emojiPopup?.dismiss()
keyboardController?.hide()
onSend()
},
Expand Down
Loading
Loading