mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-19 23:51:30 +00:00
SS-75 Open URL modal change
This commit is contained in:
parent
802cf19598
commit
0c83606539
@ -2,15 +2,21 @@ package org.thoughtcrime.securesms
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Typeface
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.AttributeSet
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.style.StyleSpan
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.LinearLayout.VERTICAL
|
import android.widget.LinearLayout.VERTICAL
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.Space
|
import android.widget.Space
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@ -22,7 +28,9 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.core.view.updateMargins
|
import androidx.core.view.updateMargins
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.squareup.phrase.Phrase
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.utilities.StringSubstitutionConstants.URL_KEY
|
||||||
import org.thoughtcrime.securesms.conversation.v2.Util.writeTextToClipboard
|
import org.thoughtcrime.securesms.conversation.v2.Util.writeTextToClipboard
|
||||||
import org.thoughtcrime.securesms.util.toPx
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
|
|
||||||
@ -33,20 +41,22 @@ annotation class DialogDsl
|
|||||||
@DialogDsl
|
@DialogDsl
|
||||||
class SessionDialogBuilder(val context: Context) {
|
class SessionDialogBuilder(val context: Context) {
|
||||||
|
|
||||||
private val dp20 = toPx(20, context.resources)
|
val dp20 = toPx(20, context.resources)
|
||||||
private val dp40 = toPx(40, context.resources)
|
val dp40 = toPx(40, context.resources)
|
||||||
private val dp60 = toPx(60, context.resources)
|
val dp60 = toPx(60, context.resources)
|
||||||
|
|
||||||
private val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(context)
|
private val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||||
|
|
||||||
private var dialog: AlertDialog? = null
|
private var dialog: AlertDialog? = null
|
||||||
private fun dismiss() = dialog?.dismiss()
|
fun dismiss() = dialog?.dismiss()
|
||||||
|
|
||||||
private val topView = LinearLayout(context)
|
private val topView = LinearLayout(context)
|
||||||
.apply { setPadding(0, dp20, 0, 0) }
|
.apply { setPadding(0, dp20, 0, 0) }
|
||||||
.apply { orientation = VERTICAL }
|
.apply { orientation = VERTICAL }
|
||||||
.also(dialogBuilder::setCustomTitle)
|
.also(dialogBuilder::setCustomTitle)
|
||||||
private val contentView = LinearLayout(context).apply { orientation = VERTICAL }
|
|
||||||
|
val contentView = LinearLayout(context).apply { orientation = VERTICAL }
|
||||||
|
|
||||||
private val buttonLayout = LinearLayout(context)
|
private val buttonLayout = LinearLayout(context)
|
||||||
|
|
||||||
private val root = LinearLayout(context).apply { orientation = VERTICAL }
|
private val root = LinearLayout(context).apply { orientation = VERTICAL }
|
||||||
@ -56,39 +66,24 @@ class SessionDialogBuilder(val context: Context) {
|
|||||||
addView(buttonLayout)
|
addView(buttonLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun title(@StringRes id: Int) = title(context.getString(id))
|
// Main title entry point
|
||||||
|
|
||||||
fun title(text: CharSequence?) = title(text?.toString())
|
|
||||||
fun title(text: String?) {
|
fun title(text: String?) {
|
||||||
text(text, R.style.TextAppearance_AppCompat_Title) { setPadding(dp20, 0, dp20, 0) }
|
text(text, R.style.TextAppearance_AppCompat_Title) { setPadding(dp20, 0, dp20, 0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenience assessor for title that takes a string resource
|
||||||
|
fun title(@StringRes id: Int) = title(context.getString(id))
|
||||||
|
|
||||||
|
// Convenience accessor for title that takes a CharSequence
|
||||||
|
fun title(text: CharSequence?) = title(text?.toString())
|
||||||
|
|
||||||
fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style)
|
fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style)
|
||||||
|
|
||||||
fun text(text: CharSequence?, @StyleRes style: Int = 0) {
|
fun text(text: CharSequence?, @StyleRes style: Int = 0) {
|
||||||
text(text, style) {
|
text(text, style) {
|
||||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||||
.apply { updateMargins(dp40, 0, dp40, 0) }
|
.apply { updateMargins(dp40, 0, dp40, 0) }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun textWithMaxOfFiveLines(text: CharSequence?, @StyleRes style: Int = 0) {
|
|
||||||
|
|
||||||
ScrollView(context, null, 0).apply {
|
|
||||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
|
||||||
|
|
||||||
// fix this so it adds and shows a scrollbar if it exceeds 5 lines
|
|
||||||
here!
|
|
||||||
text(text, style) {
|
|
||||||
maxLines = 5
|
|
||||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
|
||||||
.apply { updateMargins(dp40, 0, dp40, 0) }
|
|
||||||
}.apply { refreshDrawableState() }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun text(text: CharSequence?, @StyleRes style: Int, modify: TextView.() -> Unit) {
|
private fun text(text: CharSequence?, @StyleRes style: Int, modify: TextView.() -> Unit) {
|
||||||
@ -148,11 +143,11 @@ class SessionDialogBuilder(val context: Context) {
|
|||||||
) { listener() }
|
) { listener() }
|
||||||
|
|
||||||
fun okButton(listener: (() -> Unit) = {}) = button(android.R.string.ok) { listener() }
|
fun okButton(listener: (() -> Unit) = {}) = button(android.R.string.ok) { listener() }
|
||||||
|
|
||||||
fun cancelButton(listener: (() -> Unit) = {}) = button(android.R.string.cancel, R.string.AccessibilityId_cancel) { listener() }
|
fun cancelButton(listener: (() -> Unit) = {}) = button(android.R.string.cancel, R.string.AccessibilityId_cancel) { listener() }
|
||||||
|
|
||||||
fun copyUrlButton(listener: (() -> Unit) = {}) = button(android.R.string.copyUrl, R.string.AccessibilityId_copy) { listener() }
|
fun copyUrlButton(listener: (() -> Unit) = {}) = button(android.R.string.copyUrl, R.string.AccessibilityId_copy) { listener() }
|
||||||
|
|
||||||
|
|
||||||
fun button(
|
fun button(
|
||||||
@StringRes text: Int,
|
@StringRes text: Int,
|
||||||
@StringRes contentDescriptionRes: Int = text,
|
@StringRes contentDescriptionRes: Int = text,
|
||||||
@ -176,32 +171,125 @@ class SessionDialogBuilder(val context: Context) {
|
|||||||
fun Context.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
fun Context.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
SessionDialogBuilder(this).apply { build() }.show()
|
SessionDialogBuilder(this).apply { build() }.show()
|
||||||
|
|
||||||
private fun Context.showOpenUrlDialogInner(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
// Method to show a dialog used to open or copy a URL
|
||||||
SessionDialogBuilder(this).apply {
|
fun Context.showOpenUrlDialog(url: String, showCloseButton: Boolean = true): AlertDialog {
|
||||||
title(R.string.urlOpen)
|
|
||||||
text(R.string.urlOpenBrowser)
|
|
||||||
build()
|
|
||||||
}.show()
|
|
||||||
|
|
||||||
fun Context.showOpenUrlDialogPublicFacing(url: String): AlertDialog {
|
|
||||||
return SessionDialogBuilder(this).apply {
|
return SessionDialogBuilder(this).apply {
|
||||||
|
// If we're not showing a close button we can just use a simple title..
|
||||||
|
if (!showCloseButton) {
|
||||||
title(R.string.urlOpen)
|
title(R.string.urlOpen)
|
||||||
val txt = getString(R.string.urlOpenBrowser) + "\n\n" + "https://github.com/oxen-io/session-android/theworldslongrsturlisverylongindeedandshouldgoover5linesbecausethatswhatIneedtotestbecausemaryhadalittlelamb" //url
|
} else {
|
||||||
textWithMaxOfFiveLines(txt)
|
// ..otherwise we have to jump through some hoops to add a close button.
|
||||||
dangerButton(R.string.open) { openUrl(url) }
|
|
||||||
|
// Create a RelativeLayout as the container for the custom title
|
||||||
|
val titleLayout = RelativeLayout(context).apply {
|
||||||
|
layoutParams = RelativeLayout.LayoutParams(
|
||||||
|
RelativeLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a TextView for the title
|
||||||
|
val titleTextView = TextView(context).apply {
|
||||||
|
// Set the text and display it in the correct 'title' style
|
||||||
|
text = context.getString(R.string.urlOpen)
|
||||||
|
setTextAppearance(R.style.TextAppearance_AppCompat_Title)
|
||||||
|
|
||||||
|
layoutParams = RelativeLayout.LayoutParams(
|
||||||
|
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply {
|
||||||
|
addRule(RelativeLayout.CENTER_HORIZONTAL)
|
||||||
|
addRule(RelativeLayout.CENTER_VERTICAL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an ImageButton for the close button
|
||||||
|
val closeButton = ImageButton(context).apply {
|
||||||
|
setImageResource(android.R.drawable.ic_menu_close_clear_cancel) // Use a standard Android close icon
|
||||||
|
background = null // Remove the background to make it look like an icon
|
||||||
|
layoutParams = RelativeLayout.LayoutParams(
|
||||||
|
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply {
|
||||||
|
addRule(RelativeLayout.ALIGN_PARENT_END) // Place the close button on the "right" side
|
||||||
|
addRule(RelativeLayout.CENTER_VERTICAL)
|
||||||
|
}
|
||||||
|
contentDescription = context.getString(R.string.close)
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Close the dialog when the button is clicked
|
||||||
|
closeButton.setOnClickListener { dismiss() }
|
||||||
|
|
||||||
|
// Add the TextView and ImageButton to the RelativeLayout..
|
||||||
|
titleLayout.addView(titleTextView)
|
||||||
|
titleLayout.addView(closeButton)
|
||||||
|
|
||||||
|
// ..and then add that layout to the contentView.
|
||||||
|
contentView.addView(titleLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a TextView for the "Are you sure you want to open this URL?"
|
||||||
|
val txtView = TextView(context).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||||
|
.apply { updateMargins(dp40, 0, dp40, 0) }
|
||||||
|
|
||||||
|
// Substitute the URL into the string then make it bold
|
||||||
|
val txt = Phrase.from(context, R.string.urlOpenDescription).put(URL_KEY, url).format().toString()
|
||||||
|
val txtWithBoldedURL = SpannableString(txt)
|
||||||
|
val urlStart = txt.indexOf(url)
|
||||||
|
if (urlStart >= 0) {
|
||||||
|
txtWithBoldedURL.setSpan(
|
||||||
|
StyleSpan(Typeface.BOLD),
|
||||||
|
urlStart,
|
||||||
|
urlStart + url.length,
|
||||||
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
text = txtWithBoldedURL
|
||||||
|
|
||||||
|
gravity = Gravity.CENTER // Center the text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a ScrollView and add the TextView to it
|
||||||
|
val scrollView = ScrollView(context).apply {
|
||||||
|
addView(txtView)
|
||||||
|
|
||||||
|
// Apply padding to the ScrollView so that the scroll bar isn't right up against the edge.
|
||||||
|
// We'll apply the same padding to both sides to keep the text centered.
|
||||||
|
setPadding(dp20, 0, dp20, 0)
|
||||||
|
|
||||||
|
// Place the scroll bar inside the container.
|
||||||
|
// See the following for how different options look: https://stackoverflow.com/questions/3103132/android-listview-scrollbarstyle
|
||||||
|
scrollBarStyle = ScrollView.SCROLLBARS_INSIDE_INSET
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the textView takes up 5 lines or more then show the scroll bar, force it to remain visible,
|
||||||
|
// and set the ScrollView height accordingly.
|
||||||
|
txtView.viewTreeObserver.addOnGlobalLayoutListener {
|
||||||
|
// Only display the vertical scroll bar if the text takes up 5 lines or more
|
||||||
|
val maxLines = 5
|
||||||
|
if (txtView.lineCount >= maxLines) {
|
||||||
|
scrollView.isVerticalScrollBarEnabled = true
|
||||||
|
scrollView.setScrollbarFadingEnabled(false)
|
||||||
|
scrollView.isVerticalFadingEdgeEnabled = false
|
||||||
|
val lineHeight = txtView.lineHeight
|
||||||
|
scrollView.layoutParams.height = lineHeight * maxLines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the ScrollView to the contentView and then add the 'Open' and 'Copy URL' buttons.
|
||||||
|
// Note: The text and contentDescription are set on the `copyUrlButton` by the function.
|
||||||
|
contentView.addView(scrollView)
|
||||||
|
dangerButton(R.string.open, R.string.AccessibilityId_urlOpenBrowser) { openUrl(url) }
|
||||||
copyUrlButton { writeTextToClipboard(context, url) }
|
copyUrlButton { writeTextToClipboard(context, url) }
|
||||||
}.show()
|
}.show()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// showOpenUrlDialogInner {
|
|
||||||
// okButton { openUrl(url) }
|
|
||||||
// cancelButton()
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
// Method to actually open a given URL via an Intent that will use the default browser
|
||||||
fun Context.openUrl(url: String) = Intent(Intent.ACTION_VIEW, Uri.parse(url)).let(::startActivity)
|
fun Context.openUrl(url: String) = Intent(Intent.ACTION_VIEW, Uri.parse(url)).let(::startActivity)
|
||||||
|
|
||||||
fun Fragment.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
fun Fragment.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
SessionDialogBuilder(requireContext()).apply { build() }.show()
|
SessionDialogBuilder(requireContext()).apply { build() }.show()
|
||||||
|
|
||||||
fun Fragment.createSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
fun Fragment.createSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
SessionDialogBuilder(requireContext()).apply { build() }.create()
|
SessionDialogBuilder(requireContext()).apply { build() }.create()
|
||||||
|
@ -8,20 +8,16 @@ import android.view.MotionEvent
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.bumptech.glide.RequestManager
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewLinkPreviewBinding
|
import network.loki.messenger.databinding.ViewLinkPreviewBinding
|
||||||
import org.session.libsession.utilities.getColorFromAttr
|
import org.session.libsession.utilities.getColorFromAttr
|
||||||
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.components.CornerMask
|
import org.thoughtcrime.securesms.components.CornerMask
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import com.bumptech.glide.RequestManager
|
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.SessionDialogBuilder
|
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
|
import org.thoughtcrime.securesms.showOpenUrlDialog
|
||||||
import org.thoughtcrime.securesms.showOpenUrlDialogPublicFacing
|
|
||||||
|
|
||||||
|
|
||||||
class LinkPreviewView : LinearLayout {
|
class LinkPreviewView : LinearLayout {
|
||||||
private val binding: ViewLinkPreviewBinding by lazy { ViewLinkPreviewBinding.bind(this) }
|
private val binding: ViewLinkPreviewBinding by lazy { ViewLinkPreviewBinding.bind(this) }
|
||||||
@ -89,17 +85,11 @@ class LinkPreviewView : LinearLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openURL() {
|
// Method to show the open or copy URL dialog
|
||||||
|
private fun openURL() {
|
||||||
val url = this.url ?: return Log.w("LinkPreviewView", "Cannot open a null URL")
|
val url = this.url ?: return Log.w("LinkPreviewView", "Cannot open a null URL")
|
||||||
val activity = context as AppCompatActivity
|
val activity = context as AppCompatActivity
|
||||||
|
activity.showOpenUrlDialog(url)
|
||||||
// OLDE!
|
|
||||||
//ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
|
|
||||||
|
|
||||||
activity.showOpenUrlDialogPublicFacing(url)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
|||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
|
import org.thoughtcrime.securesms.showOpenUrlDialog
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||||
import org.thoughtcrime.securesms.util.SearchUtil
|
import org.thoughtcrime.securesms.util.SearchUtil
|
||||||
import org.thoughtcrime.securesms.util.getAccentColor
|
import org.thoughtcrime.securesms.util.getAccentColor
|
||||||
@ -293,7 +294,7 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
val updatedUrl = urlSpan.url.let { it.toHttpUrlOrNull().toString() }
|
||||||
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
val replacementSpan = ModalURLSpan(updatedUrl) { url ->
|
||||||
val activity = context as AppCompatActivity
|
val activity = context as AppCompatActivity
|
||||||
ModalUrlBottomSheet(url).show(activity.supportFragmentManager, "Open URL Dialog")
|
activity.showOpenUrlDialog(url)
|
||||||
}
|
}
|
||||||
val start = body.getSpanStart(urlSpan)
|
val start = body.getSpanStart(urlSpan)
|
||||||
val end = body.getSpanEnd(urlSpan)
|
val end = body.getSpanEnd(urlSpan)
|
||||||
|
@ -122,11 +122,13 @@
|
|||||||
|
|
||||||
<style name="Widget.Session.Button.Dialog.UnimportantText">
|
<style name="Widget.Session.Button.Dialog.UnimportantText">
|
||||||
<item name="android:background">@drawable/unimportant_dialog_text_button_background</item>
|
<item name="android:background">@drawable/unimportant_dialog_text_button_background</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.Session.Button.Dialog.DangerText">
|
<style name="Widget.Session.Button.Dialog.DangerText">
|
||||||
<item name="android:background">@drawable/danger_dialog_text_button_background</item>
|
<item name="android:background">@drawable/danger_dialog_text_button_background</item>
|
||||||
<item name="android:textColor">?danger</item>
|
<item name="android:textColor">?danger</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.Session.EditText.Compose" parent="@style/Signal.Text.Body">
|
<style name="Widget.Session.EditText.Compose" parent="@style/Signal.Text.Body">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user