Increase stories caption limit to 1500 grapheme clusters.

fork-5.53.8
Alex Hart 2022-09-19 14:24:44 -03:00 zatwierdzone przez Cody Henthorne
rodzic 654b602cef
commit 9326c1726a
14 zmienionych plików z 125 dodań i 58 usunięć

Wyświetl plik

@ -3,10 +3,8 @@ package org.thoughtcrime.securesms.components
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import org.whispersystems.signalservice.api.util.Preconditions
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
/** /**
@ -18,8 +16,6 @@ class ViewBinderDelegate<T : ViewBinding>(private val bindingFactory: (View) ->
private var binding: T? = null private var binding: T? = null
operator fun getValue(thisRef: Fragment, property: KProperty<*>): T { operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {
Preconditions.checkState(thisRef.viewLifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED))
if (binding == null) { if (binding == null) {
thisRef.viewLifecycleOwner.lifecycle.addObserver(this@ViewBinderDelegate) thisRef.viewLifecycleOwner.lifecycle.addObserver(this@ViewBinderDelegate)
binding = bindingFactory(thisRef.requireView()) binding = bindingFactory(thisRef.requireView())

Wyświetl plik

@ -164,7 +164,7 @@ class MediaSelectionRepository(context: Context) {
} else { } else {
val iterator = BreakIteratorCompat.getInstance() val iterator = BreakIteratorCompat.getInstance()
iterator.setText(body) iterator.setText(body)
iterator.take(Stories.MAX_BODY_SIZE).toString() iterator.take(Stories.MAX_CAPTION_SIZE).toString()
} }
} }

Wyświetl plik

@ -5,21 +5,27 @@ import android.os.Bundle
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.processors.BehaviorProcessor
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.BehaviorSubject import io.reactivex.rxjava3.subjects.BehaviorSubject
import io.reactivex.rxjava3.subjects.PublishSubject import io.reactivex.rxjava3.subjects.PublishSubject
import io.reactivex.rxjava3.subjects.Subject import io.reactivex.rxjava3.subjects.Subject
import org.signal.core.util.BreakIteratorCompat
import org.thoughtcrime.securesms.components.mention.MentionAnnotation import org.thoughtcrime.securesms.components.mention.MentionAnnotation
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
import org.thoughtcrime.securesms.conversation.MessageSendType import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.mediasend.Media import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
import org.thoughtcrime.securesms.mediasend.VideoEditorFragment import org.thoughtcrime.securesms.mediasend.VideoEditorFragment
import org.thoughtcrime.securesms.mediasend.v2.review.AddMessageCharacterCount
import org.thoughtcrime.securesms.mms.MediaConstraints import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.mms.SentMediaQuality import org.thoughtcrime.securesms.mms.SentMediaQuality
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
@ -53,6 +59,8 @@ class MediaSelectionViewModel(
) )
) )
private val addAMessageUpdatePublisher = BehaviorProcessor.create<CharSequence>()
val isContactSelectionRequired = destination == MediaSelectionDestination.ChooseAfterMediaSelection val isContactSelectionRequired = destination == MediaSelectionDestination.ChooseAfterMediaSelection
val state: LiveData<MediaSelectionState> = store.stateLiveData val state: LiveData<MediaSelectionState> = store.stateLiveData
@ -64,6 +72,22 @@ class MediaSelectionViewModel(
private val disposables = CompositeDisposable() private val disposables = CompositeDisposable()
fun watchAddAMessageCount(): Flowable<AddMessageCharacterCount> {
return addAMessageUpdatePublisher
.onBackpressureLatest()
.map {
val iterator = BreakIteratorCompat.getInstance()
iterator.setText(it)
AddMessageCharacterCount(iterator.countBreaks())
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
fun updateAddAMessageCount(input: CharSequence?) {
addAMessageUpdatePublisher.onNext(input ?: "")
}
private val isMeteredDisposable: Disposable = repository.isMetered.subscribe { metered -> private val isMeteredDisposable: Disposable = repository.isMetered.subscribe { metered ->
store.update { store.update {
it.copy( it.copy(

Wyświetl plik

@ -0,0 +1,21 @@
package org.thoughtcrime.securesms.mediasend.v2.review
import org.thoughtcrime.securesms.stories.Stories
import kotlin.math.max
/**
* Manages the current character count for the add-message input.
*
* We only want to display the count if DISPLAY_COUNT or less characters remain.
* The actual count is calculated in the background by the ViewModel.
*/
@JvmInline
value class AddMessageCharacterCount(private val count: Int) {
fun getRemaining(): Int = max(Stories.MAX_CAPTION_SIZE - count, 0)
fun shouldDisplayCount(): Boolean = getRemaining() <= DISPLAY_COUNT_THRESHOLD
companion object {
private const val DISPLAY_COUNT_THRESHOLD = 50
}
}

Wyświetl plik

@ -7,6 +7,7 @@ import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
@ -14,10 +15,8 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import org.signal.core.util.EditTextUtil import org.signal.core.util.EditTextUtil
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.ComposeText
import org.thoughtcrime.securesms.components.InputAwareLayout
import org.thoughtcrime.securesms.components.KeyboardEntryDialogFragment import org.thoughtcrime.securesms.components.KeyboardEntryDialogFragment
import org.thoughtcrime.securesms.components.emoji.EmojiToggle import org.thoughtcrime.securesms.components.ViewBinderDelegate
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.conversation.ui.inlinequery.InlineQuery import org.thoughtcrime.securesms.conversation.ui.inlinequery.InlineQuery
@ -27,6 +26,7 @@ import org.thoughtcrime.securesms.conversation.ui.inlinequery.InlineQueryResults
import org.thoughtcrime.securesms.conversation.ui.inlinequery.InlineQueryViewModel import org.thoughtcrime.securesms.conversation.ui.inlinequery.InlineQueryViewModel
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerFragment import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerFragment
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel
import org.thoughtcrime.securesms.databinding.V2MediaAddMessageDialogFragmentBinding
import org.thoughtcrime.securesms.keyboard.KeyboardPage import org.thoughtcrime.securesms.keyboard.KeyboardPage
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
@ -58,11 +58,8 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
ownerProducer = { requireActivity() } ownerProducer = { requireActivity() }
) )
private lateinit var input: ComposeText private val binding by ViewBinderDelegate(V2MediaAddMessageDialogFragmentBinding::bind)
private lateinit var emojiDrawerToggle: EmojiToggle
private lateinit var emojiDrawerStub: Stub<MediaKeyboard> private lateinit var emojiDrawerStub: Stub<MediaKeyboard>
private lateinit var hud: InputAwareLayout
private lateinit var mentionsContainer: ViewGroup
private lateinit var inlineQueryResultsController: InlineQueryResultsController private lateinit var inlineQueryResultsController: InlineQueryResultsController
private var requestedEmojiDrawer: Boolean = false private var requestedEmojiDrawer: Boolean = false
@ -79,28 +76,34 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
input = view.findViewById(R.id.add_a_message_input) emojiDrawerStub = Stub(binding.content.emojiDrawerStub)
if (Stories.isFeatureEnabled()) { if (Stories.isFeatureEnabled()) {
EditTextUtil.addGraphemeClusterLimitFilter(input, Stories.MAX_BODY_SIZE) EditTextUtil.addGraphemeClusterLimitFilter(binding.content.addAMessageInput, Stories.MAX_CAPTION_SIZE)
} }
input.setText(requireArguments().getCharSequence(ARG_INITIAL_TEXT)) binding.content.addAMessageInput.addTextChangedListener(afterTextChanged = {
viewModel.updateAddAMessageCount(it)
})
binding.content.addAMessageInput.setText(requireArguments().getCharSequence(ARG_INITIAL_TEXT))
emojiDrawerToggle = view.findViewById(R.id.emoji_toggle)
emojiDrawerStub = Stub(view.findViewById(R.id.emoji_drawer_stub))
if (SignalStore.settings().isPreferSystemEmoji) { if (SignalStore.settings().isPreferSystemEmoji) {
emojiDrawerToggle.visible = false binding.content.emojiToggle.visible = false
} else { } else {
emojiDrawerToggle.setOnClickListener { onEmojiToggleClicked() } binding.content.emojiToggle.setOnClickListener { onEmojiToggleClicked() }
} }
hud = view.findViewById(R.id.hud) binding.hud.setOnClickListener { dismissAllowingStateLoss() }
hud.setOnClickListener { dismissAllowingStateLoss() }
val confirm: View = view.findViewById(R.id.confirm_button) val confirm: View = view.findViewById(R.id.confirm_button)
confirm.setOnClickListener { dismissAllowingStateLoss() } confirm.setOnClickListener { dismissAllowingStateLoss() }
disposables += viewModel.watchAddAMessageCount().subscribe { count ->
binding.content.addAMessageLimit.visible = count.shouldDisplayCount()
binding.content.addAMessageLimit.text = count.getRemaining().toString()
}
disposables.add( disposables.add(
viewModel.hudCommands.observeOn(AndroidSchedulers.mainThread()).subscribe { viewModel.hudCommands.observeOn(AndroidSchedulers.mainThread()).subscribe {
when (it) { when (it) {
@ -120,18 +123,18 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
super.onResume() super.onResume()
requestedEmojiDrawer = false requestedEmojiDrawer = false
ViewUtil.focusAndShowKeyboard(input) ViewUtil.focusAndShowKeyboard(binding.content.addAMessageInput)
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
ViewUtil.hideKeyboard(requireContext(), input) ViewUtil.hideKeyboard(requireContext(), binding.content.addAMessageInput)
} }
override fun onDismiss(dialog: DialogInterface) { override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog) super.onDismiss(dialog)
viewModel.setMessage(input.text) viewModel.setMessage(binding.content.addAMessageInput.text)
} }
override fun onKeyboardHidden() { override fun onKeyboardHidden() {
@ -151,23 +154,21 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
super.onDestroyView() super.onDestroyView()
disposables.dispose() disposables.dispose()
input.setInlineQueryChangedListener(null) binding.content.addAMessageInput.setInlineQueryChangedListener(null)
input.setMentionValidator(null) binding.content.addAMessageInput.setMentionValidator(null)
} }
private fun initializeMentions() { private fun initializeMentions() {
mentionsContainer = requireView().findViewById(R.id.mentions_picker_container)
inlineQueryResultsController = InlineQueryResultsController( inlineQueryResultsController = InlineQueryResultsController(
requireContext(), requireContext(),
inlineQueryViewModel, inlineQueryViewModel,
requireView().findViewById(R.id.background_holder), requireView().findViewById(R.id.background_holder),
(requireView() as ViewGroup), (requireView() as ViewGroup),
input, binding.content.addAMessageInput,
viewLifecycleOwner viewLifecycleOwner
) )
input.setInlineQueryChangedListener(object : InlineQueryChangedListener { binding.content.addAMessageInput.setInlineQueryChangedListener(object : InlineQueryChangedListener {
override fun onQueryChanged(inlineQuery: InlineQuery) { override fun onQueryChanged(inlineQuery: InlineQuery) {
when (inlineQuery) { when (inlineQuery) {
is InlineQuery.Mention -> { is InlineQuery.Mention -> {
@ -196,7 +197,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
disposables += inlineQueryViewModel disposables += inlineQueryViewModel
.selection .selection
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { r -> input.replaceText(r) } .subscribe { r -> binding.content.addAMessageInput.replaceText(r) }
val recipientId: RecipientId = viewModel.destination.getRecipientSearchKey()?.recipientId ?: return val recipientId: RecipientId = viewModel.destination.getRecipientSearchKey()?.recipientId ?: return
@ -204,7 +205,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
this.recipient = recipient this.recipient = recipient
mentionsViewModel.onRecipientChange(recipient) mentionsViewModel.onRecipientChange(recipient)
input.setMentionValidator { annotations -> binding.content.addAMessageInput.setMentionValidator { annotations ->
if (!recipient.isPushV2Group) { if (!recipient.isPushV2Group) {
annotations annotations
} else { } else {
@ -221,7 +222,7 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
} }
mentionsViewModel.selectedRecipient.observe(viewLifecycleOwner) { recipient -> mentionsViewModel.selectedRecipient.observe(viewLifecycleOwner) { recipient ->
input.replaceTextWithMention(recipient.getDisplayName(requireContext()), recipient.id) binding.content.addAMessageInput.replaceTextWithMention(recipient.getDisplayName(requireContext()), recipient.id)
} }
} }
@ -239,17 +240,17 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
if (!emojiDrawerStub.resolved()) { if (!emojiDrawerStub.resolved()) {
keyboardPagerViewModel.setOnlyPage(KeyboardPage.EMOJI) keyboardPagerViewModel.setOnlyPage(KeyboardPage.EMOJI)
emojiDrawerStub.get().setFragmentManager(childFragmentManager) emojiDrawerStub.get().setFragmentManager(childFragmentManager)
emojiDrawerToggle.attach(emojiDrawerStub.get()) binding.content.emojiToggle.attach(emojiDrawerStub.get())
} }
if (hud.currentInput == emojiDrawerStub.get()) { if (binding.hud.currentInput == emojiDrawerStub.get()) {
requestedEmojiDrawer = false requestedEmojiDrawer = false
hud.showSoftkey(input) binding.hud.showSoftkey(binding.content.addAMessageInput)
} else { } else {
requestedEmojiDrawer = true requestedEmojiDrawer = true
hud.hideSoftkey(input) { binding.hud.hideSoftkey(binding.content.addAMessageInput) {
hud.post { binding.hud.post {
hud.show(input, emojiDrawerStub.get()) binding.hud.show(binding.content.addAMessageInput, emojiDrawerStub.get())
} }
} }
} }
@ -268,11 +269,11 @@ class AddMessageDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_a
} }
private fun onEmojiSelected(emoji: String?) { private fun onEmojiSelected(emoji: String?) {
input.insertEmoji(emoji) binding.content.addAMessageInput.insertEmoji(emoji)
} }
private fun onKeyEvent(keyEvent: KeyEvent?) { private fun onKeyEvent(keyEvent: KeyEvent?) {
input.dispatchKeyEvent(keyEvent) binding.content.addAMessageInput.dispatchKeyEvent(keyEvent)
} }
companion object { companion object {

Wyświetl plik

@ -168,7 +168,7 @@ public final class MultiShareArgs implements Parcelable {
BreakIteratorCompat breakIteratorCompat = BreakIteratorCompat.getInstance(); BreakIteratorCompat breakIteratorCompat = BreakIteratorCompat.getInstance();
breakIteratorCompat.setText(getDraftText()); breakIteratorCompat.setText(getDraftText());
if (breakIteratorCompat.countBreaks() > Stories.MAX_BODY_SIZE) { if (breakIteratorCompat.countBreaks() > Stories.MAX_TEXT_STORY_SIZE) {
return false; return false;
} }
} }

Wyświetl plik

@ -432,7 +432,7 @@ public final class MultiShareSender {
BreakIteratorCompat breakIteratorCompat = BreakIteratorCompat.getInstance(); BreakIteratorCompat breakIteratorCompat = BreakIteratorCompat.getInstance();
breakIteratorCompat.setText(draftText); breakIteratorCompat.setText(draftText);
String trimmed = breakIteratorCompat.take(Stories.MAX_BODY_SIZE).toString(); String trimmed = breakIteratorCompat.take(Stories.MAX_TEXT_STORY_SIZE).toString();
if (linkPreview == null) { if (linkPreview == null) {
return trimmed; return trimmed;
} }

Wyświetl plik

@ -47,7 +47,8 @@ object Stories {
private val TAG = Log.tag(Stories::class.java) private val TAG = Log.tag(Stories::class.java)
const val MAX_BODY_SIZE = 700 const val MAX_TEXT_STORY_SIZE = 700
const val MAX_CAPTION_SIZE = 1500
@JvmField @JvmField
val MAX_VIDEO_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(30) val MAX_VIDEO_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(30)

Wyświetl plik

@ -12,7 +12,9 @@ import android.media.AudioManager
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.view.GestureDetector import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent import android.view.MotionEvent
import android.view.ScaleGestureDetector import android.view.ScaleGestureDetector
import android.view.View import android.view.View
@ -826,9 +828,16 @@ class StoryViewerPageFragment :
} }
private fun onShowCaptionOverlay(caption: TextView, largeCaption: TextView, largeCaptionOverlay: View) { private fun onShowCaptionOverlay(caption: TextView, largeCaption: TextView, largeCaptionOverlay: View) {
sharedViewModel.setIsChildScrolling(true)
caption.visible = false caption.visible = false
largeCaption.visible = true largeCaption.visible = true
largeCaptionOverlay.visible = true largeCaptionOverlay.visible = true
largeCaption.movementMethod = ScrollingMovementMethod()
largeCaption.scrollY = 0
largeCaption.setOnClickListener {
onHideCaptionOverlay(caption, largeCaption, largeCaptionOverlay)
}
largeCaptionOverlay.setOnClickListener { largeCaptionOverlay.setOnClickListener {
onHideCaptionOverlay(caption, largeCaption, largeCaptionOverlay) onHideCaptionOverlay(caption, largeCaption, largeCaptionOverlay)
} }
@ -839,8 +848,10 @@ class StoryViewerPageFragment :
caption.visible = true caption.visible = true
largeCaption.visible = false largeCaption.visible = false
largeCaptionOverlay.visible = false largeCaptionOverlay.visible = false
largeCaption.setOnClickListener(null)
largeCaptionOverlay.setOnClickListener(null) largeCaptionOverlay.setOnClickListener(null)
viewModel.setIsDisplayingCaptionOverlay(false) viewModel.setIsDisplayingCaptionOverlay(false)
sharedViewModel.setIsChildScrolling(false)
} }
private fun presentFrom(from: TextView, storyPost: StoryPost) { private fun presentFrom(from: TextView, storyPost: StoryPost) {

Wyświetl plik

@ -25,7 +25,10 @@ data class StoryViewerPlaybackState(
) { ) {
val hideChromeImmediate: Boolean = isRunningSharedElementAnimation val hideChromeImmediate: Boolean = isRunningSharedElementAnimation
val hideChrome: Boolean = isRunningSharedElementAnimation || isUserLongTouching || isUserScrollingChild || isUserScaling val hideChrome: Boolean = isRunningSharedElementAnimation ||
isUserLongTouching ||
(isUserScrollingChild && !isDisplayingCaptionOverlay) ||
isUserScaling
val isPaused: Boolean = !areSegmentsInitialized || val isPaused: Boolean = !areSegmentsInitialized ||
isUserTouching || isUserTouching ||

Wyświetl plik

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="@color/core_grey_75"/> <solid android:color="@color/signal_dark_colorSurfaceVariant"/>
<corners android:radius="20dp"/> <corners android:radius="18dp"/>
</shape> </shape>

Wyświetl plik

@ -132,14 +132,14 @@
<org.thoughtcrime.securesms.components.emoji.EmojiTextView <org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/story_large_caption" android:id="@+id/story_large_caption"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:gravity="bottom"
android:textAppearance="@style/Signal.Text.Body" android:textAppearance="@style/Signal.Text.Body"
android:visibility="gone" android:visibility="gone"
android:scrollbars="vertical"
app:layout_constrainedHeight="true" app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="@id/story_from_barrier" app:layout_constraintBottom_toTopOf="@id/story_from_barrier"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

Wyświetl plik

@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.InputAwareLayout xmlns:android="http://schemas.android.com/apk/res/android" <org.thoughtcrime.securesms.components.InputAwareLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/hud" android:id="@+id/hud"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<include layout="@layout/v2_media_add_message_dialog_fragment_content" /> <include android:id="@+id/content" layout="@layout/v2_media_add_message_dialog_fragment_content" />
</org.thoughtcrime.securesms.components.InputAwareLayout> </org.thoughtcrime.securesms.components.InputAwareLayout>

Wyświetl plik

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -26,7 +25,7 @@
android:layout_height="0dp" android:layout_height="0dp"
android:background="@drawable/rounded_rectangle_secondary_dark" android:background="@drawable/rounded_rectangle_secondary_dark"
app:layout_constraintBottom_toBottomOf="@id/add_a_message_input" app:layout_constraintBottom_toBottomOf="@id/add_a_message_input"
app:layout_constraintEnd_toEndOf="@id/add_a_message_input" app:layout_constraintEnd_toEndOf="@id/add_a_message_limit"
app:layout_constraintStart_toStartOf="@id/emoji_toggle" app:layout_constraintStart_toStartOf="@id/emoji_toggle"
app:layout_constraintTop_toTopOf="@id/add_a_message_input" /> app:layout_constraintTop_toTopOf="@id/add_a_message_input" />
@ -49,7 +48,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="6dp" app:layout_goneMarginEnd="6dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:background="@null" android:background="@null"
android:hint="@string/MediaReviewFragment__add_a_message" android:hint="@string/MediaReviewFragment__add_a_message"
@ -61,11 +60,25 @@
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:textAppearance="@style/Signal.Text.Body" android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toTopOf="@id/emoji_drawer_stub" app:layout_constraintBottom_toTopOf="@id/emoji_drawer_stub"
app:layout_constraintEnd_toStartOf="@id/confirm_button" app:layout_constraintEnd_toStartOf="@id/add_a_message_limit"
app:layout_constraintStart_toEndOf="@id/emoji_toggle" app:layout_constraintStart_toEndOf="@id/emoji_toggle"
app:layout_constraintTop_toTopOf="@id/input_barrier" app:layout_constraintTop_toTopOf="@id/input_barrier"
app:layout_goneMarginStart="12dp" /> app:layout_goneMarginStart="12dp" />
<TextView
android:id="@+id/add_a_message_limit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:paddingEnd="12dp"
android:textAppearance="@style/Signal.Text.BodySmall"
android:textColor="@color/signal_colorOnSurfaceVariant"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/add_a_message_input"
app:layout_constraintEnd_toStartOf="@id/confirm_button"
tools:text="50"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/confirm_button" android:id="@+id/confirm_button"
android:layout_width="48dp" android:layout_width="48dp"