Fix emoji keyboard bugs and group story replies.

fork-5.53.8
Cody Henthorne 2022-03-31 16:43:30 -04:00
rodzic b8bb2e234b
commit 11c3ea769e
6 zmienionych plików z 96 dodań i 3 usunięć

Wyświetl plik

@ -0,0 +1,14 @@
package com.google.android.material.bottomsheet
import android.view.View
import android.widget.FrameLayout
import java.lang.ref.WeakReference
/**
* Manually adjust the nested scrolling child for a given [BottomSheetBehavior].
*/
object BottomSheetBehaviorHack {
fun setNestedScrollingChild(behavior: BottomSheetBehavior<FrameLayout>, view: View) {
behavior.nestedScrollingChildRef = WeakReference(view)
}
}

Wyświetl plik

@ -146,6 +146,10 @@ public class MediaKeyboard extends FrameLayout implements InputView {
.commitAllowingStateLoss(); .commitAllowingStateLoss();
} }
public boolean isEmojiSearchMode() {
return keyboardState == State.EMOJI_SEARCH;
}
private void initView() { private void initView() {
if (!isInitialised) { if (!isInitialised) {

Wyświetl plik

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.ComposeText import org.thoughtcrime.securesms.components.ComposeText
import org.thoughtcrime.securesms.components.InputAwareLayout import org.thoughtcrime.securesms.components.InputAwareLayout
import org.thoughtcrime.securesms.components.QuoteView import org.thoughtcrime.securesms.components.QuoteView
import org.thoughtcrime.securesms.components.emoji.EmojiPageView
import org.thoughtcrime.securesms.components.emoji.EmojiToggle import org.thoughtcrime.securesms.components.emoji.EmojiToggle
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard import org.thoughtcrime.securesms.components.emoji.MediaKeyboard
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
@ -42,6 +43,9 @@ class StoryReplyComposer @JvmOverloads constructor(
var callback: Callback? = null var callback: Callback? = null
val emojiPageView: EmojiPageView?
get() = findViewById(R.id.emoji_page_view)
init { init {
inflate(context, R.layout.stories_reply_to_story_composer, this) inflate(context, R.layout.stories_reply_to_story_composer, this)
@ -85,6 +89,12 @@ class StoryReplyComposer @JvmOverloads constructor(
emojiDrawerToggle.setOnClickListener { emojiDrawerToggle.setOnClickListener {
onEmojiToggleClicked() onEmojiToggleClicked()
} }
inputAwareLayout.addOnKeyboardShownListener {
if (inputAwareLayout.currentInput == emojiDrawer && !emojiDrawer.isEmojiSearchMode) {
onEmojiToggleClicked()
}
}
} }
fun setQuote(messageRecord: MediaMmsMessageRecord) { fun setQuote(messageRecord: MediaMmsMessageRecord) {
@ -136,11 +146,13 @@ class StoryReplyComposer @JvmOverloads constructor(
if (inputAwareLayout.currentInput == emojiDrawer) { if (inputAwareLayout.currentInput == emojiDrawer) {
isRequestingEmojiDrawer = false isRequestingEmojiDrawer = false
inputAwareLayout.showSoftkey(input) inputAwareLayout.showSoftkey(input)
callback?.onHideEmojiKeyboard()
} else { } else {
isRequestingEmojiDrawer = true isRequestingEmojiDrawer = true
inputAwareLayout.hideSoftkey(input) { inputAwareLayout.hideSoftkey(input) {
inputAwareLayout.post { inputAwareLayout.post {
inputAwareLayout.show(input, emojiDrawer) inputAwareLayout.show(input, emojiDrawer)
emojiDrawer.post { callback?.onShowEmojiKeyboard() }
} }
} }
} }
@ -150,6 +162,8 @@ class StoryReplyComposer @JvmOverloads constructor(
fun onSendActionClicked() fun onSendActionClicked()
fun onPickReactionClicked() fun onPickReactionClicked()
fun onInitializeEmojiDrawer(mediaKeyboard: MediaKeyboard) fun onInitializeEmojiDrawer(mediaKeyboard: MediaKeyboard)
fun onShowEmojiKeyboard() = Unit
fun onHideEmojiKeyboard() = Unit
} }
companion object { companion object {

Wyświetl plik

@ -37,6 +37,8 @@ class StoryGroupReplyBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDi
override val peekHeightPercentage: Float = 1f override val peekHeightPercentage: Float = 1f
private val lifecycleDisposable = LifecycleDisposable() private val lifecycleDisposable = LifecycleDisposable()
private var shouldShowFullScreen = false
private var initialParentHeight = 0
private val storyViewerPageViewModel: StoryViewerPageViewModel by viewModels( private val storyViewerPageViewModel: StoryViewerPageViewModel by viewModels(
ownerProducer = { requireParentFragment() } ownerProducer = { requireParentFragment() }
@ -70,7 +72,16 @@ class StoryGroupReplyBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDi
view.viewTreeObserver.addOnGlobalLayoutListener { view.viewTreeObserver.addOnGlobalLayoutListener {
val parentHeight = requireCoordinatorLayout().height val parentHeight = requireCoordinatorLayout().height
val desiredHeight = (resources.displayMetrics.heightPixels * 0.6f).roundToInt() val desiredHeight = (resources.displayMetrics.heightPixels * 0.6f).roundToInt()
val targetHeight = if (parentHeight != 0) min(parentHeight, desiredHeight) else desiredHeight
if (initialParentHeight == 0) {
initialParentHeight = parentHeight
}
val targetHeight = when {
parentHeight == 0 -> desiredHeight
shouldShowFullScreen || parentHeight != initialParentHeight -> parentHeight
else -> min(parentHeight, desiredHeight)
}
if (view.height != targetHeight) { if (view.height != targetHeight) {
view.updateLayoutParams { view.updateLayoutParams {
@ -90,6 +101,11 @@ class StoryGroupReplyBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDi
storyViewerPageViewModel.startDirectReply(storyId, recipientId) storyViewerPageViewModel.startDirectReply(storyId, recipientId)
} }
override fun requestFullScreen(fullscreen: Boolean) {
shouldShowFullScreen = fullscreen
requireView().invalidate()
}
companion object { companion object {
private const val ARG_STORY_ID = "arg.story.id" private const val ARG_STORY_ID = "arg.story.id"
private const val ARG_GROUP_RECIPIENT_ID = "arg.group.recipient.id" private const val ARG_GROUP_RECIPIENT_ID = "arg.group.recipient.id"

Wyświetl plik

@ -2,19 +2,22 @@ package org.thoughtcrime.securesms.stories.viewer.reply.group
import android.content.ClipData import android.content.ClipData
import android.os.Bundle import android.os.Bundle
import android.provider.Settings.System.getConfiguration
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehaviorHack
import com.google.android.material.bottomsheet.BottomSheetDialog
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialogFragment
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard import org.thoughtcrime.securesms.components.emoji.MediaKeyboard
import org.thoughtcrime.securesms.components.mention.MentionAnnotation import org.thoughtcrime.securesms.components.mention.MentionAnnotation
import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLConfiguration
@ -72,6 +75,18 @@ class StoryGroupReplyFragment :
ownerProducer = { requireActivity() } ownerProducer = { requireActivity() }
) )
private val recyclerListener: RecyclerView.OnItemTouchListener = object : RecyclerView.SimpleOnItemTouchListener() {
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
recyclerView.isNestedScrollingEnabled = view == recyclerView
composer.emojiPageView?.isNestedScrollingEnabled = view == composer.emojiPageView
val dialog = (parentFragment as FixedRoundedCornerBottomSheetDialogFragment).dialog as BottomSheetDialog
BottomSheetBehaviorHack.setNestedScrollingChild(dialog.behavior, view)
dialog.findViewById<View>(R.id.design_bottom_sheet)?.invalidate()
return false
}
}
private val colorizer = Colorizer() private val colorizer = Colorizer()
private val lifecycleDisposable = LifecycleDisposable() private val lifecycleDisposable = LifecycleDisposable()
@ -245,6 +260,18 @@ class StoryGroupReplyFragment :
mediaKeyboard.setFragmentManager(childFragmentManager) mediaKeyboard.setFragmentManager(childFragmentManager)
} }
override fun onShowEmojiKeyboard() {
requireListener<Callback>().requestFullScreen(true)
recyclerView.addOnItemTouchListener(recyclerListener)
composer.emojiPageView?.addOnItemTouchListener(recyclerListener)
}
override fun onHideEmojiKeyboard() {
recyclerView.removeOnItemTouchListener(recyclerListener)
composer.emojiPageView?.removeOnItemTouchListener(recyclerListener)
requireListener<Callback>().requestFullScreen(false)
}
override fun openEmojiSearch() { override fun openEmojiSearch() {
composer.openEmojiSearch() composer.openEmojiSearch()
} }
@ -359,5 +386,6 @@ class StoryGroupReplyFragment :
interface Callback { interface Callback {
fun onStartDirectReply(recipientId: RecipientId) fun onStartDirectReply(recipientId: RecipientId)
fun requestFullScreen(fullscreen: Boolean)
} }
} }

Wyświetl plik

@ -48,6 +48,9 @@ class StoryViewsAndRepliesDialogFragment : FixedRoundedCornerBottomSheetDialogFr
private lateinit var pager: ViewPager2 private lateinit var pager: ViewPager2
private var shouldShowFullScreen = false
private var initialParentHeight = 0
private val storyViewerPageViewModel: StoryViewerPageViewModel by viewModels( private val storyViewerPageViewModel: StoryViewerPageViewModel by viewModels(
ownerProducer = { requireParentFragment() } ownerProducer = { requireParentFragment() }
) )
@ -96,7 +99,16 @@ class StoryViewsAndRepliesDialogFragment : FixedRoundedCornerBottomSheetDialogFr
view.viewTreeObserver.addOnGlobalLayoutListener { view.viewTreeObserver.addOnGlobalLayoutListener {
val parentHeight = requireCoordinatorLayout().height val parentHeight = requireCoordinatorLayout().height
val desiredHeight = (resources.displayMetrics.heightPixels * 0.6f).roundToInt() val desiredHeight = (resources.displayMetrics.heightPixels * 0.6f).roundToInt()
val targetHeight = if (parentHeight != 0) min(parentHeight, desiredHeight) else desiredHeight
if (initialParentHeight == 0) {
initialParentHeight = parentHeight
}
val targetHeight = when {
parentHeight == 0 -> desiredHeight
shouldShowFullScreen || parentHeight != initialParentHeight -> parentHeight
else -> min(parentHeight, desiredHeight)
}
if (view.height != targetHeight) { if (view.height != targetHeight) {
view.updateLayoutParams { view.updateLayoutParams {
@ -126,6 +138,11 @@ class StoryViewsAndRepliesDialogFragment : FixedRoundedCornerBottomSheetDialogFr
storyViewerPageViewModel.startDirectReply(storyId, recipientId) storyViewerPageViewModel.startDirectReply(storyId, recipientId)
} }
override fun requestFullScreen(fullscreen: Boolean) {
shouldShowFullScreen = fullscreen
requireView().invalidate()
}
private inner class PageChangeCallback : ViewPager2.OnPageChangeCallback() { private inner class PageChangeCallback : ViewPager2.OnPageChangeCallback() {
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {
if (state == ViewPager2.SCROLL_STATE_IDLE) { if (state == ViewPager2.SCROLL_STATE_IDLE) {