mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-21 17:05:39 +03:00
[merge] Fix compile
Change-Id: I5df927a88f4eb786561a86d8986155ebe71baafd
This commit is contained in:
parent
3291517b8b
commit
a10220f690
51 changed files with 157 additions and 151 deletions
|
@ -49,7 +49,7 @@ public class ColorMatrixListPreference extends ListPreference {
|
|||
}
|
||||
|
||||
public ColorMatrixListPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.dialogPreferenceStyle);
|
||||
this(context, attrs, android.R.attr.dialogPreferenceStyle);
|
||||
}
|
||||
|
||||
public ColorMatrixListPreference(Context context) {
|
||||
|
|
|
@ -18,7 +18,6 @@ package im.vector.app.core.epoxy.profiles.notifications
|
|||
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
|
@ -29,7 +28,7 @@ import im.vector.app.core.epoxy.ClickListener
|
|||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
|
||||
/**
|
||||
* SC: copy of RadioButtonItem, but with extra icon + different layout
|
||||
|
@ -65,10 +64,10 @@ abstract class BottomSheetRadioButtonItem : VectorEpoxyModel<BottomSheetRadioBut
|
|||
|
||||
if (selected) {
|
||||
holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_on))
|
||||
holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked)
|
||||
holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_checked)
|
||||
} else {
|
||||
holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off))
|
||||
holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked)
|
||||
holder.radioImage.contentDescription = holder.view.context.getString(CommonStrings.a11y_unchecked)
|
||||
}
|
||||
|
||||
holder.icon.setImageResource(iconRes ?: 0)
|
||||
|
|
|
@ -43,17 +43,13 @@ fun renderReactionImage(reactionUrl: String?,
|
|||
.load(url)
|
||||
.centerCrop()
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>, isFirstResource: Boolean): Boolean {
|
||||
Timber.w("Reaction image load failed for $effectiveReactionUrl: $e")
|
||||
textView.isVisible = true
|
||||
imageView.isVisible = false
|
||||
return false
|
||||
}
|
||||
override fun onResourceReady(resource: Drawable?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>?,
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean): Boolean {
|
||||
override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>?, dataSource: DataSource, isFirstResource: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
|
|
@ -63,7 +63,7 @@ class ImageContentRendererDataLoader(private val context: Context) :
|
|||
}
|
||||
|
||||
class ImageContentRendererDataFetcher(
|
||||
context: Context,
|
||||
private val context: Context,
|
||||
private val data: ImageContentRenderer.Data,
|
||||
private val width: Int,
|
||||
private val height: Int
|
||||
|
|
|
@ -143,7 +143,7 @@ open class VectorPreference : Preference {
|
|||
} else {
|
||||
val bgDrawable = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, bgDrawable, true)
|
||||
ViewCompat.setBackground(itemView, ContextCompat.getDrawable(context, bgDrawable.resourceId))
|
||||
itemView.background = ContextCompat.getDrawable(context, bgDrawable.resourceId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "onBindView")
|
||||
|
|
|
@ -92,7 +92,7 @@ class VectorSwitchPreference : SwitchPreference {
|
|||
} else {
|
||||
val bgDrawable = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, bgDrawable, true)
|
||||
ViewCompat.setBackground(itemView, ContextCompat.getDrawable(context, bgDrawable.resourceId))
|
||||
itemView.background = ContextCompat.getDrawable(context, bgDrawable.resourceId)
|
||||
}
|
||||
|
||||
super.onBindViewHolder(holder)
|
||||
|
|
|
@ -9,8 +9,6 @@ import android.view.View
|
|||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.text.getSpans
|
||||
import androidx.core.text.toSpanned
|
||||
import androidx.core.view.ViewCompat.LAYOUT_DIRECTION_RTL
|
||||
import im.vector.app.R
|
||||
import im.vector.app.features.html.HtmlCodeSpan
|
||||
import io.noties.markwon.core.spans.EmphasisSpan
|
||||
import kotlin.math.ceil
|
||||
|
@ -67,7 +65,7 @@ interface AbstractFooteredTextView {
|
|||
val lastLine = layout.lineCount - 1
|
||||
|
||||
// Let's check if the last line's text has the same RTL behaviour as the layout direction.
|
||||
val viewIsRtl = layoutDirection == LAYOUT_DIRECTION_RTL
|
||||
val viewIsRtl = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||
val looksLikeRtl = layout.getParagraphDirection(lastLine) == Layout.DIR_RIGHT_TO_LEFT
|
||||
/*
|
||||
val lastVisibleCharacter = layout.getLineVisibleEnd(lastLine) - 1
|
||||
|
@ -104,7 +102,7 @@ interface AbstractFooteredTextView {
|
|||
if (looksLikeRtl == viewIsRtl)
|
||||
widthLastLine
|
||||
else
|
||||
(maxLineWidth + resources.getDimensionPixelSize(R.dimen.sc_footer_rtl_mismatch_extra_padding))
|
||||
(maxLineWidth + resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_rtl_mismatch_extra_padding))
|
||||
) + footerState.footerWidth
|
||||
|
||||
// If the last line is a multi-line code block, we have never space in the last line (as the black background always uses full width)
|
||||
|
@ -139,12 +137,12 @@ interface AbstractFooteredTextView {
|
|||
newHeight += footerState.footerHeight
|
||||
// Ensure enough width for footer bellow
|
||||
newWidth = max(newWidth, footerState.footerWidth +
|
||||
resources.getDimensionPixelSize(R.dimen.sc_footer_padding_compensation) +
|
||||
2 * resources.getDimensionPixelSize(R.dimen.sc_footer_overlay_padding))
|
||||
resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_padding_compensation) +
|
||||
2 * resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_overlay_padding))
|
||||
}
|
||||
|
||||
if (addItalicPadding) {
|
||||
newWidth += resources.getDimensionPixelSize(R.dimen.italic_text_view_extra_padding)
|
||||
newWidth += resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.italic_text_view_extra_padding)
|
||||
}
|
||||
|
||||
//setMeasuredDimension(newWidth, newHeight)
|
||||
|
|
|
@ -9,7 +9,7 @@ import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrap
|
|||
|
||||
interface BubbleDependentView<H: VectorEpoxyHolder> {
|
||||
|
||||
fun getScBubbleMargin(resources: Resources): Int = resources.getDimensionPixelSize(R.dimen.dual_bubble_one_side_without_avatar_margin)
|
||||
fun getScBubbleMargin(resources: Resources): Int = resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.dual_bubble_one_side_without_avatar_margin)
|
||||
fun getViewStubMinimumWidth(holder: H): Int = 0
|
||||
|
||||
fun allowFooterOverlay(holder: H, bubbleWrapView: ScMessageBubbleWrapView): Boolean = false
|
||||
|
|
|
@ -23,7 +23,7 @@ class FooteredTextView @JvmOverloads constructor(
|
|||
setMeasuredDimension(updatedMeasures.first, updatedMeasures.second)
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas?) {
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
updateFooterOnPreDraw(canvas)
|
||||
|
||||
super.onDraw(canvas)
|
||||
|
|
|
@ -46,8 +46,8 @@ class JoinConferenceView @JvmOverloads constructor(
|
|||
super.onAttachedToWindow()
|
||||
views = ViewJoinConferenceBinding.bind(this)
|
||||
views?.joinConferenceButton?.setOnClickListener { onJoinClicked?.invoke() }
|
||||
val colorFrom = ThemeUtils.getColor(context, R.attr.conference_animation_from)
|
||||
val colorTo = ThemeUtils.getColor(context, R.attr.conference_animation_to)
|
||||
val colorFrom = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.conference_animation_from)
|
||||
val colorTo = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.conference_animation_to)
|
||||
// Animate button color to highlight
|
||||
backgroundAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
|
||||
repeatMode = ValueAnimator.REVERSE
|
||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.app.features.autocomplete.member.AutocompleteEmojiDataItem
|
|||
import im.vector.app.features.reactions.data.EmojiDataSource
|
||||
import im.vector.app.features.reactions.data.EmojiItem
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
@ -123,7 +124,7 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
|
|||
val currentRoomEmotes = room.getAllEmojiItems(query)
|
||||
val allEmoteData = currentRoomEmotes.toAutocompleteItems().let {
|
||||
if (it.isNotEmpty()) {
|
||||
listOf(AutocompleteEmojiDataItem.Header(roomId, context.getString(R.string.custom_emotes_this_room))) + it
|
||||
listOf(AutocompleteEmojiDataItem.Header(roomId, context.getString(CommonStrings.custom_emotes_this_room))) + it
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
@ -145,7 +146,7 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
|
|||
emoteData += listOf(
|
||||
AutocompleteEmojiDataItem.Header(
|
||||
AutocompleteEmojiController.ACCOUNT_DATA_EMOTE_ID,
|
||||
context.getString(R.string.custom_emotes_account_data)
|
||||
context.getString(CommonStrings.custom_emotes_account_data)
|
||||
)
|
||||
)
|
||||
emoteData += userPack.toAutocompleteItems()
|
||||
|
@ -188,13 +189,13 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
|
|||
packRoomId,
|
||||
if (packName != null) {
|
||||
context.getString(
|
||||
R.string.custom_emotes_named_other_room,
|
||||
CommonStrings.custom_emotes_named_other_room,
|
||||
packName,
|
||||
packRoomName
|
||||
)
|
||||
} else {
|
||||
context.getString(
|
||||
R.string.custom_emotes_other_room,
|
||||
CommonStrings.custom_emotes_other_room,
|
||||
packRoomName
|
||||
)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import im.vector.app.core.epoxy.ClickListener
|
|||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.lib.strings.CommonPlurals
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
|
||||
@EpoxyModelClass // Re-using item_autocomplete_emoji to avoid class-cast exceptions like https://github.com/SchildiChat/SchildiChat-android-rageshakes/issues/1040
|
||||
abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.Holder>(R.layout.item_autocomplete_emoji) {
|
||||
|
@ -43,13 +45,13 @@ abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.H
|
|||
holder.emoteImage.isVisible = true
|
||||
holder.emojiNameText.isVisible = true
|
||||
holder.emoteImage.setImageResource(R.drawable.ic_expand_more)
|
||||
holder.emoteImage.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.emoteImage.context, R.attr.vctr_content_secondary))
|
||||
holder.emoteImage.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.emoteImage.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary))
|
||||
holder.emojiText.typeface = Typeface.DEFAULT
|
||||
count.let {
|
||||
if (it == null) {
|
||||
holder.emojiNameText.setText(R.string.room_profile_section_more)
|
||||
holder.emojiNameText.setText(CommonStrings.room_profile_section_more)
|
||||
} else {
|
||||
holder.emojiNameText.text = holder.emojiNameText.resources.getQuantityString(R.plurals.message_reaction_show_more, it, it)
|
||||
holder.emojiNameText.text = holder.emojiNameText.resources.getQuantityString(CommonPlurals.message_reaction_show_more, it, it)
|
||||
}
|
||||
}
|
||||
holder.emojiKeywordText.isVisible = false
|
||||
|
|
|
@ -40,6 +40,7 @@ import im.vector.app.features.session.coroutineScope
|
|||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.lib.core.utils.flow.chunk
|
||||
import im.vector.lib.core.utils.timer.CountUpTimer
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -308,7 +309,7 @@ class WebRtcCall(
|
|||
add(
|
||||
PeerConnection
|
||||
.IceServer
|
||||
.builder("stun:" + stringProvider.getString(R.string.fallback_stun_server_url))
|
||||
.builder("stun:" + stringProvider.getString(im.vector.app.config.R.string.fallback_stun_server_url))
|
||||
.createIceServer()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
|
|||
pr.transactionId,
|
||||
)
|
||||
}
|
||||
colorAttribute = R.attr.verification_request_background
|
||||
colorAttribute = im.vector.lib.ui.styles.R.attr.verification_request_background
|
||||
// 5mn expiration
|
||||
expirationTimestamp = clock.epochMillis() + (5 * 60 * 1000L)
|
||||
}
|
||||
|
|
|
@ -162,10 +162,10 @@ fun BaseEpoxyVerificationController.renderAcceptDeclineRequest() {
|
|||
bottomSheetVerificationActionItem {
|
||||
id("accept_pr")
|
||||
title(host.stringProvider.getString(CommonStrings.action_accept))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
// subTitle(host.stringProvider.getString(CommonStrings.verification_request_start_notice))
|
||||
iconRes(R.drawable.ic_arrow_right)
|
||||
iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
listener { host.listener?.acceptRequest() }
|
||||
}
|
||||
bottomSheetVerificationActionItem {
|
||||
|
@ -253,9 +253,9 @@ fun BaseEpoxyVerificationController.buildSasCodeActions() {
|
|||
bottomSheetVerificationActionItem {
|
||||
id("ok")
|
||||
title(host.stringProvider.getString(CommonStrings.verification_sas_match))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
iconRes(R.drawable.ic_check_on)
|
||||
iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
listener { host.listener?.onMatchButtonTapped() }
|
||||
}
|
||||
}
|
||||
|
@ -356,9 +356,9 @@ fun BaseEpoxyVerificationController.renderQrTransaction(transaction: Verificatio
|
|||
bottomSheetVerificationActionItem {
|
||||
id("confirm")
|
||||
title(host.stringProvider.getString(CommonStrings.qr_code_scanned_by_other_yes))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
titleColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
iconRes(R.drawable.ic_check_on)
|
||||
iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color))
|
||||
iconColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color))
|
||||
listener { host.listener?.onUserConfirmsQrCodeScanned() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -645,8 +645,8 @@ class HomeActivity :
|
|||
resources,
|
||||
menu.findItem(R.id.dev_base_theme),
|
||||
R.id.dev_base_theme_group,
|
||||
R.array.theme_entries,
|
||||
R.array.theme_values,
|
||||
im.vector.lib.strings.R.array.theme_entries,
|
||||
im.vector.lib.strings.R.array.theme_values,
|
||||
ThemeUtils.getCurrentActiveTheme(this)
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveTheme(this, value)
|
||||
|
|
|
@ -957,8 +957,8 @@ class TimelineFragment :
|
|||
resources,
|
||||
menu.findItem(R.id.dev_base_theme),
|
||||
R.id.dev_base_theme_group,
|
||||
R.array.theme_entries,
|
||||
R.array.theme_values,
|
||||
im.vector.lib.strings.R.array.theme_entries,
|
||||
im.vector.lib.strings.R.array.theme_values,
|
||||
ThemeUtils.getCurrentActiveTheme(requireContext())
|
||||
) { value ->
|
||||
ThemeUtils.setCurrentActiveTheme(requireContext(), value)
|
||||
|
@ -1129,7 +1129,7 @@ class TimelineFragment :
|
|||
val badgeDrawable = DrawableCompat.wrap(badgeFrameLayout.background)
|
||||
val color = ThemeUtils.getColor(
|
||||
requireContext(),
|
||||
if (userIsMentioned) R.attr.colorError else R.attr.colorAccent)
|
||||
if (userIsMentioned) com.google.android.material.R.attr.colorError else com.google.android.material.R.attr.colorAccent
|
||||
)
|
||||
DrawableCompat.setTint(badgeDrawable, color)
|
||||
badgeFrameLayout.background = badgeDrawable
|
||||
|
@ -1569,10 +1569,10 @@ class TimelineFragment :
|
|||
views.includeRoomToolbar.roomToolbarSubtitleView.apply {
|
||||
setTextOrHide(subtitle)
|
||||
if (typingMessage.isNullOrBlank()) {
|
||||
setTextColor(colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary))
|
||||
setTextColor(colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_content_secondary))
|
||||
setTypeface(null, Typeface.NORMAL)
|
||||
} else {
|
||||
setTextColor(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
|
||||
setTextColor(colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorPrimary))
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -558,7 +558,7 @@ class MessageComposerFragment : VectorBaseFragment<FragmentComposerBinding>(), A
|
|||
}
|
||||
|
||||
private fun handleSendButtonVisibilityChanged(event: MessageComposerViewEvents.AnimateSendButtonVisibility) {
|
||||
val sendButtonColor = ThemeUtils.getColor(views.composerLayout.context, if (event.isActive) R.attr.colorAccent else R.attr.vctr_content_tertiary)
|
||||
val sendButtonColor = ThemeUtils.getColor(views.composerLayout.context, if (event.isActive) com.google.android.material.R.attr.colorAccent else im.vector.lib.ui.styles.R.attr.vctr_content_tertiary)
|
||||
views.composerLayout.sendButton.imageTintList = ColorStateList.valueOf(sendButtonColor)
|
||||
if (event.isVisible) {
|
||||
if (views.composerLayout.sendButton.isVisible) {
|
||||
|
|
|
@ -124,7 +124,7 @@ class ViewEditHistoryEpoxyController @Inject constructor(
|
|||
diff_match_patch.Operation.INSERT -> {
|
||||
span {
|
||||
text = it.text
|
||||
textColor = colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color)
|
||||
textColor = colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_encrypting_message_text_color)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
|
|
@ -85,7 +85,7 @@ class DisplayableEventFormatter @Inject constructor(
|
|||
timelineEvent.getVectorLastMessageContent()?.let { messageContent ->
|
||||
when (messageContent.msgType) {
|
||||
MessageType.MSGTYPE_TEXT -> {
|
||||
val body = messageContent.getTextDisplayableContent(imageFallback = stringProvider.getString(R.string.sent_an_image))
|
||||
val body = messageContent.getTextDisplayableContent(imageFallback = stringProvider.getString(CommonStrings.sent_an_image))
|
||||
if (messageContent is MessageTextContent && messageContent.matrixFormattedBody.isNullOrBlank().not()) {
|
||||
val localFormattedBody = htmlRenderer.get().parse(body) as Document
|
||||
val renderedBody = htmlRenderer.get().render(localFormattedBody) ?: body
|
||||
|
@ -115,11 +115,11 @@ class DisplayableEventFormatter @Inject constructor(
|
|||
}
|
||||
}
|
||||
MessageType.MSGTYPE_VIDEO -> {
|
||||
val text = (messageContent as? MessageWithAttachmentContent)?.getCaption() ?: stringProvider.getString(CommonStrings.string.sent_a_video)
|
||||
val text = (messageContent as? MessageWithAttachmentContent)?.getCaption() ?: stringProvider.getString(CommonStrings.sent_a_video)
|
||||
simpleFormat(senderName, text, appendAuthor)
|
||||
}
|
||||
MessageType.MSGTYPE_FILE -> {
|
||||
val text = (messageContent as? MessageWithAttachmentContent)?.getCaption() ?: stringProvider.getString(CommonStrings.string.sent_a_file)
|
||||
val text = (messageContent as? MessageWithAttachmentContent)?.getCaption() ?: stringProvider.getString(CommonStrings.sent_a_file)
|
||||
simpleFormat(senderName, text, appendAuthor)
|
||||
}
|
||||
MessageType.MSGTYPE_LOCATION -> {
|
||||
|
@ -210,7 +210,7 @@ class DisplayableEventFormatter @Inject constructor(
|
|||
(event.getClearContent().toModel() as? MessageContent)?.let { messageContent ->
|
||||
when (messageContent.msgType) {
|
||||
MessageType.MSGTYPE_TEXT -> {
|
||||
val body = messageContent.getTextDisplayableContent(imageFallback = stringProvider.getString(R.string.sent_an_image))
|
||||
val body = messageContent.getTextDisplayableContent(imageFallback = stringProvider.getString(CommonStrings.sent_an_image))
|
||||
if (messageContent is MessageTextContent && messageContent.matrixFormattedBody.isNullOrBlank().not()) {
|
||||
val localFormattedBody = htmlRenderer.get().parse(body) as Document
|
||||
val renderedBody = htmlRenderer.get().render(localFormattedBody) ?: body
|
||||
|
|
|
@ -48,7 +48,7 @@ class MatrixItemColorProvider @Inject constructor(
|
|||
USER_COLORING_FROM_PL -> {
|
||||
colorProvider.getColorFromAttribute(
|
||||
when {
|
||||
userInRoomInformation?.userPowerLevel == null -> R.attr.colorAccent // This is also used for avatars in the room overview
|
||||
userInRoomInformation?.userPowerLevel == null -> com.google.android.material.R.attr.colorAccent // This is also used for avatars in the room overview
|
||||
userInRoomInformation.userPowerLevel >= 100 -> R.attr.user_color_pl_100
|
||||
userInRoomInformation.userPowerLevel >= 95 -> R.attr.user_color_pl_95
|
||||
userInRoomInformation.userPowerLevel >= 51 -> R.attr.user_color_pl_51
|
||||
|
|
|
@ -172,16 +172,16 @@ abstract class AbsBaseMessageItem<H : AbsBaseMessageItem.Holder>(@LayoutRes layo
|
|||
// else: dual-side bubbles (getBubbleMargin should not get called for other bubbleStyles)
|
||||
|
||||
// Direct chats usually have avatars hidden on both sides
|
||||
baseAttributes.informationData.isDirect -> resources.getDimensionPixelSize(R.dimen.dual_bubble_both_sides_without_avatar_margin)
|
||||
baseAttributes.informationData.isDirect -> resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.dual_bubble_both_sides_without_avatar_margin)
|
||||
// No direct chat, but sent by me: other side has an avatar
|
||||
baseAttributes.informationData.sentByMe -> {
|
||||
resources.getDimensionPixelSize(R.dimen.dual_bubble_one_side_without_avatar_margin) +
|
||||
resources.getDimensionPixelSize(R.dimen.dual_bubble_one_side_avatar_offset) +
|
||||
resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.dual_bubble_one_side_without_avatar_margin) +
|
||||
resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.dual_bubble_one_side_avatar_offset) +
|
||||
// SC bubbles use SMALL avatars
|
||||
ceil(AvatarSizeProvider.Companion.AvatarStyle.SMALL.avatarSizeDP * resources.displayMetrics.density).toInt()
|
||||
}
|
||||
// No direct chat, sent by other: my side has hidden avatar
|
||||
else -> resources.getDimensionPixelSize(R.dimen.dual_bubble_one_side_without_avatar_margin)
|
||||
else -> resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.dual_bubble_one_side_without_avatar_margin)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,11 +118,11 @@ abstract class MessageFileItem : AbsMessageItem<MessageFileItem.Holder>() {
|
|||
override fun getViewStubMinimumWidth(holder: Holder): Int {
|
||||
// Guess text width for name and time
|
||||
// On first call, holder.fileImageView.width is not initialized yet
|
||||
val imageWidth = holder.fileImageView.resources.getDimensionPixelSize(R.dimen.file_icon_size)
|
||||
val imageWidth = holder.fileImageView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.file_icon_size)
|
||||
val minimumWidthWithText =
|
||||
ceil(guessTextWidth(holder.filenameView, filename)).toInt() +
|
||||
imageWidth +
|
||||
holder.filenameView.resources.getDimensionPixelSize(R.dimen.sc_bubble_guess_minimum_width_padding)
|
||||
holder.filenameView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_bubble_guess_minimum_width_padding)
|
||||
val absoluteMinimumWidth = imageWidth*3
|
||||
return max(absoluteMinimumWidth, minimumWidthWithText)
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLay
|
|||
import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess
|
||||
import im.vector.app.features.media.ImageContentRenderer
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt
|
||||
|
@ -77,8 +78,8 @@ class InReplyToView @JvmOverloads constructor(
|
|||
|
||||
private var state: PreviewReplyUiState = PreviewReplyUiState.NoReply
|
||||
|
||||
private val maxThumbnailWidth = context.resources.getDimensionPixelSize(R.dimen.reply_thumbnail_max_width)
|
||||
private val maxThumbnailHeight = context.resources.getDimensionPixelSize(R.dimen.reply_thumbnail_height)
|
||||
private val maxThumbnailWidth = context.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.reply_thumbnail_max_width)
|
||||
private val maxThumbnailHeight = context.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.reply_thumbnail_height)
|
||||
|
||||
/**
|
||||
* This methods is responsible for rendering the view according to the newState
|
||||
|
@ -150,8 +151,8 @@ class InReplyToView @JvmOverloads constructor(
|
|||
hideViews()
|
||||
isVisible = true
|
||||
views.replyTextView.isVisible = true
|
||||
val color = ThemeUtils.getColor(context, R.attr.vctr_content_secondary)
|
||||
views.replyTextView.text = SpannableString(context.getString(R.string.in_reply_to_loading)).apply {
|
||||
val color = ThemeUtils.getColor(context,im.vector.lib.ui.styles.R.attr.vctr_content_secondary)
|
||||
views.replyTextView.text = SpannableString(context.getString(CommonStrings.in_reply_to_loading)).apply {
|
||||
setSpan(StyleSpan(Typeface.ITALIC), 0, length, 0)
|
||||
setSpan(ForegroundColorSpan(color), 0, length, 0)
|
||||
}
|
||||
|
@ -163,8 +164,8 @@ class InReplyToView @JvmOverloads constructor(
|
|||
isVisible = true
|
||||
Timber.w(state.throwable, "Error rendering reply")
|
||||
views.replyTextView.isVisible = true
|
||||
val color = ThemeUtils.getColor(context, R.attr.vctr_content_secondary)
|
||||
views.replyTextView.text = SpannableString(context.getString(R.string.in_reply_to_error)).apply {
|
||||
val color = ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary)
|
||||
views.replyTextView.text = SpannableString(context.getString(CommonStrings.in_reply_to_error)).apply {
|
||||
setSpan(StyleSpan(Typeface.ITALIC), 0, length, 0)
|
||||
setSpan(ForegroundColorSpan(color), 0, length, 0)
|
||||
}
|
||||
|
@ -201,7 +202,7 @@ class InReplyToView @JvmOverloads constructor(
|
|||
|
||||
private fun renderRedacted() {
|
||||
views.replyTextView.isVisible = true
|
||||
views.replyTextView.setText(R.string.event_redacted)
|
||||
views.replyTextView.setText(CommonStrings.event_redacted)
|
||||
}
|
||||
|
||||
private fun renderTextContent(
|
||||
|
@ -333,21 +334,21 @@ class InReplyToView @JvmOverloads constructor(
|
|||
val bgColor = when (val layout = informationData.messageLayout) {
|
||||
is TimelineMessageLayout.ScBubble -> {
|
||||
if (informationData.sentByMe && !layout.singleSidedLayout) {
|
||||
ThemeUtils.getColor(context, R.attr.sc_message_bg_outgoing)
|
||||
ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.sc_message_bg_outgoing)
|
||||
} else {
|
||||
ThemeUtils.getColor(context, R.attr.sc_message_bg_incoming)
|
||||
ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.sc_message_bg_incoming)
|
||||
}
|
||||
}
|
||||
is TimelineMessageLayout.Bubble -> {
|
||||
if (layout.isPseudoBubble) {
|
||||
0
|
||||
} else {
|
||||
val backgroundColorAttr = if (informationData.sentByMe) R.attr.vctr_message_bubble_outbound else R.attr.vctr_message_bubble_inbound
|
||||
val backgroundColorAttr = if (informationData.sentByMe) im.vector.lib.ui.styles.R.attr.vctr_message_bubble_outbound else im.vector.lib.ui.styles.R.attr.vctr_message_bubble_inbound
|
||||
ThemeUtils.getColor(context, backgroundColorAttr)
|
||||
}
|
||||
}
|
||||
is TimelineMessageLayout.Default -> {
|
||||
ThemeUtils.getColor(context, R.attr.vctr_system)
|
||||
ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.vctr_system)
|
||||
}
|
||||
}
|
||||
val fadeView = views.expandableReplyView.getChildAt(1)
|
||||
|
|
|
@ -50,8 +50,8 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
|
||||
init {
|
||||
inflate(context, R.layout.view_message_bubble_sc, this)
|
||||
context.withStyledAttributes(attrs, R.styleable.MessageBubble) {
|
||||
isIncoming = getBoolean(R.styleable.MessageBubble_incoming_style, false)
|
||||
context.withStyledAttributes(attrs, im.vector.lib.ui.styles.R.styleable.MessageBubble) {
|
||||
isIncoming = getBoolean(im.vector.lib.ui.styles.R.styleable.MessageBubble_incoming_style, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,7 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
renderStubMessageLayout(messageLayout, views.viewStubContainer.root)
|
||||
|
||||
// Padding for views that align with the bubble (should be roughly the bubble tail width)
|
||||
val bubbleStartAlignWidth = views.informationBottom.resources.getDimensionPixelSize(R.dimen.sc_bubble_tail_size)
|
||||
val bubbleStartAlignWidth = views.informationBottom.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_bubble_tail_size)
|
||||
if (messageLayout.reverseBubble) {
|
||||
// Align reactions container to bubble
|
||||
views.informationBottom.setPaddingRelative(
|
||||
|
@ -274,10 +274,10 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
val shortPadding: Int
|
||||
bubbleView.setBackgroundResource(messageLayout.bubbleDrawable)
|
||||
if (!messageLayout.isPseudoBubble) {
|
||||
longPadding = bubbleView.resources.getDimensionPixelSize(R.dimen.sc_bubble_inner_padding_long_side)
|
||||
shortPadding = bubbleView.resources.getDimensionPixelSize(R.dimen.sc_bubble_inner_padding_short_side)
|
||||
longPadding = bubbleView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_bubble_inner_padding_long_side)
|
||||
shortPadding = bubbleView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_bubble_inner_padding_short_side)
|
||||
} else {
|
||||
longPadding = bubbleView.resources.getDimensionPixelSize(R.dimen.sc_bubble_tail_size)
|
||||
longPadding = bubbleView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_bubble_tail_size)
|
||||
shortPadding = 0//if (attributes.informationData.showInformation && !hideSenderInformation()) { 8 } else { 0 }
|
||||
}
|
||||
if (messageLayout.reverseBubble != defaultRtl) {
|
||||
|
@ -326,8 +326,8 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
val endOf = if (defaultRtl) RelativeLayout.LEFT_OF else RelativeLayout.RIGHT_OF
|
||||
|
||||
val footerLayoutParams = views.bubbleFootView.layoutParams as RelativeLayout.LayoutParams
|
||||
var footerMarginStartDp = views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_margin_start)
|
||||
var footerMarginEndDp = views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_margin_end)
|
||||
var footerMarginStartDp = views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_margin_start)
|
||||
var footerMarginEndDp = views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_margin_end)
|
||||
if (bubbleDependentView.allowFooterOverlay(holder, this)) {
|
||||
footerLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.viewStubContainer)
|
||||
footerLayoutParams.addRule(alignEnd, R.id.viewStubContainer)
|
||||
|
@ -369,8 +369,8 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
footerLayoutParams.removeRule(startOf)
|
||||
footerLayoutParams.removeRule(RelativeLayout.BELOW)
|
||||
// Reverse margins
|
||||
footerMarginStartDp = views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_reverse_margin_start)
|
||||
footerMarginEndDp = views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_reverse_margin_end)
|
||||
footerMarginStartDp = views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_reverse_margin_start)
|
||||
footerMarginEndDp = views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_reverse_margin_end)
|
||||
}
|
||||
else -> /* footer on the right / at the end */ {
|
||||
footerLayoutParams.addRule(endOf, R.id.viewStubContainer)
|
||||
|
@ -447,25 +447,25 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs:
|
|||
|
||||
private fun styleFooterOverlay(messageLayout: TimelineMessageLayout.ScBubble) {
|
||||
views.bubbleFootView.setBackgroundResource(messageLayout.bubbleAppearance.timestampOverlay)
|
||||
tintFooter(ThemeUtils.getColor(views.bubbleFootView.context, R.attr.timestamp_overlay_fg))
|
||||
val padding = views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_overlay_padding)
|
||||
tintFooter(ThemeUtils.getColor(views.bubbleFootView.context, im.vector.lib.ui.styles.R.attr.timestamp_overlay_fg))
|
||||
val padding = views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_overlay_padding)
|
||||
views.bubbleFootView.setPaddingRelative(
|
||||
padding,
|
||||
padding,
|
||||
// compensate from inner view padding on the other side
|
||||
padding + views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_padding_compensation),
|
||||
padding + views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_padding_compensation),
|
||||
padding
|
||||
)
|
||||
}
|
||||
|
||||
private fun removeFooterOverlayStyle() {
|
||||
views.bubbleFootView.background = null
|
||||
tintFooter(ThemeUtils.getColor(views.bubbleFootView.context, R.attr.vctr_content_secondary))
|
||||
tintFooter(ThemeUtils.getColor(views.bubbleFootView.context, im.vector.lib.ui.styles.R.attr.vctr_content_secondary))
|
||||
views.bubbleFootView.setPaddingRelative(
|
||||
0,
|
||||
views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_noverlay_padding_top),
|
||||
views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_noverlay_padding_top),
|
||||
0,
|
||||
views.bubbleFootView.resources.getDimensionPixelSize(R.dimen.sc_footer_noverlay_padding_bottom)
|
||||
views.bubbleFootView.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.sc_footer_noverlay_padding_bottom)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -616,9 +616,9 @@ class RoomListFragment :
|
|||
val emptyState = when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.ALL ->
|
||||
StateView.State.Empty(
|
||||
title = getString(R.string.all_list_rooms_empty_title),
|
||||
title = getString(CommonStrings.all_list_rooms_empty_title),
|
||||
image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_group),
|
||||
message = getString(R.string.all_list_rooms_empty_body)
|
||||
message = getString(CommonStrings.all_list_rooms_empty_body)
|
||||
)
|
||||
RoomListDisplayMode.NOTIFICATIONS -> {
|
||||
StateView.State.Empty(
|
||||
|
|
|
@ -130,7 +130,7 @@ class RoomListSectionBuilder(
|
|||
addSection(
|
||||
sections = sections,
|
||||
activeSpaceUpdaters = activeSpaceAwareQueries,
|
||||
nameRes = R.string.invitations_header,
|
||||
nameRes = CommonStrings.invitations_header,
|
||||
notifyOfLocalEcho = true,
|
||||
explicitSpaceId = explicitSpaceId,
|
||||
sortOrder = sortOrder,
|
||||
|
@ -143,7 +143,7 @@ class RoomListSectionBuilder(
|
|||
addSection(
|
||||
sections,
|
||||
activeSpaceAwareQueries,
|
||||
R.string.bottom_action_favourites,
|
||||
CommonStrings.bottom_action_favourites,
|
||||
false,
|
||||
spaceFilterStrategy = if (onlyOrphansInHome) {
|
||||
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
|
||||
|
@ -160,7 +160,7 @@ class RoomListSectionBuilder(
|
|||
addSection(
|
||||
sections = sections,
|
||||
activeSpaceUpdaters = activeSpaceAwareQueries,
|
||||
nameRes = R.string.normal_priority_header,
|
||||
nameRes = CommonStrings.normal_priority_header,
|
||||
notifyOfLocalEcho = false,
|
||||
explicitSpaceId = explicitSpaceId,
|
||||
sortOrder = sortOrder,
|
||||
|
@ -177,7 +177,7 @@ class RoomListSectionBuilder(
|
|||
addSection(
|
||||
sections = sections,
|
||||
activeSpaceUpdaters = activeSpaceAwareQueries,
|
||||
nameRes = R.string.low_priority_header,
|
||||
nameRes = CommonStrings.low_priority_header,
|
||||
notifyOfLocalEcho = false,
|
||||
explicitSpaceId = explicitSpaceId,
|
||||
sortOrder = sortOrder,
|
||||
|
@ -194,7 +194,7 @@ class RoomListSectionBuilder(
|
|||
addSection(
|
||||
sections = sections,
|
||||
activeSpaceUpdaters = activeSpaceAwareQueries,
|
||||
nameRes = R.string.system_alerts_header,
|
||||
nameRes = CommonStrings.system_alerts_header,
|
||||
notifyOfLocalEcho = false,
|
||||
explicitSpaceId = explicitSpaceId,
|
||||
sortOrder = sortOrder,
|
||||
|
|
|
@ -127,9 +127,9 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>(R.layo
|
|||
// Mirror unreadCounterBadgeView colors
|
||||
holder.unreadIndentIndicator.setBackgroundColor(
|
||||
when {
|
||||
showHighlighted -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, R.attr.colorError)
|
||||
unreadNotificationCount > 0 || markedUnread -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, R.attr.colorAccent)
|
||||
hasUnreadMessage -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, R.attr.unread_line_unimportant)
|
||||
showHighlighted -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, com.google.android.material.R.attr.colorError)
|
||||
unreadNotificationCount > 0 || markedUnread -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, com.google.android.material.R.attr.colorAccent)
|
||||
hasUnreadMessage -> ThemeUtils.getColor(holder.unreadIndentIndicator.context, im.vector.lib.ui.styles.R.attr.unread_line_unimportant)
|
||||
else -> 0
|
||||
}
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.home.room.list.actions
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.bottomSheetDividerItem
|
||||
import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem
|
||||
import im.vector.app.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem
|
||||
|
|
|
@ -29,22 +29,22 @@ sealed class RoomListQuickActionsSharedAction(
|
|||
) : VectorSharedAction {
|
||||
|
||||
data class MarkUnread(val roomId: String) : RoomListQuickActionsSharedAction(
|
||||
R.string.room_list_quick_actions_mark_room_unread,
|
||||
CommonStrings.room_list_quick_actions_mark_room_unread,
|
||||
R.drawable.ic_room_actions_mark_room_unread
|
||||
)
|
||||
|
||||
data class MarkRead(val roomId: String) : RoomListQuickActionsSharedAction(
|
||||
R.string.room_list_quick_actions_mark_room_read,
|
||||
CommonStrings.room_list_quick_actions_mark_room_read,
|
||||
R.drawable.ic_room_actions_mark_room_read
|
||||
)
|
||||
|
||||
data class OpenAtBottom(val roomId: String) : RoomListQuickActionsSharedAction(
|
||||
R.string.room_list_quick_actions_open_at_bottom,
|
||||
CommonStrings.room_list_quick_actions_open_at_bottom,
|
||||
R.drawable.ic_room_actions_open_at_bottom
|
||||
)
|
||||
|
||||
data class OpenAnonymous(val roomId: String) : RoomListQuickActionsSharedAction(
|
||||
R.string.room_list_quick_actions_open_anonymous,
|
||||
CommonStrings.room_list_quick_actions_open_anonymous,
|
||||
R.drawable.ic_room_actions_open_anonymous
|
||||
)
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import im.vector.app.features.displayname.getBestName
|
|||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass
|
||||
|
@ -64,8 +65,8 @@ abstract class SpaceBarItem : VectorEpoxyModel<SpaceBarItem.Holder>(R.layout.spa
|
|||
matrixItem.let {
|
||||
if (it == null) {
|
||||
holder.avatarImageView.setImageResource(R.drawable.ic_space_home)
|
||||
holder.avatarImageView.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.avatarImageView.context, R.attr.vctr_content_primary))
|
||||
holder.avatarImageView.contentDescription = holder.rootView.context.getString(R.string.group_details_home)
|
||||
holder.avatarImageView.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.avatarImageView.context, im.vector.lib.ui.styles.R.attr.vctr_content_primary))
|
||||
holder.avatarImageView.contentDescription = holder.rootView.context.getString(CommonStrings.group_details_home)
|
||||
} else {
|
||||
holder.avatarImageView.imageTintList = null
|
||||
avatarRenderer.render(it, holder.avatarImageView)
|
||||
|
|
|
@ -84,11 +84,11 @@ abstract class ThreadListItem : VectorEpoxyModel<ThreadListItem.Holder>(R.layout
|
|||
when (threadNotificationState) {
|
||||
ThreadNotificationState.NEW_MESSAGE -> {
|
||||
holder.unreadImageView.isVisible = true
|
||||
holder.unreadImageView.setColorFilter(ThemeUtils.getColor(holder.view.context, R.attr.colorAccent))
|
||||
holder.unreadImageView.setColorFilter(ThemeUtils.getColor(holder.view.context, com.google.android.material.R.attr.colorAccent))
|
||||
}
|
||||
ThreadNotificationState.NEW_HIGHLIGHTED_MESSAGE -> {
|
||||
holder.unreadImageView.isVisible = true
|
||||
holder.unreadImageView.setColorFilter(ThemeUtils.getColor(holder.view.context, R.attr.colorError))
|
||||
holder.unreadImageView.setColorFilter(ThemeUtils.getColor(holder.view.context, com.google.android.material.R.attr.colorError))
|
||||
}
|
||||
else -> {
|
||||
holder.unreadImageView.isVisible = false
|
||||
|
|
|
@ -102,9 +102,9 @@ class EventHtmlRenderer @Inject constructor(
|
|||
}
|
||||
|
||||
private fun resolveCodeBlockBackground() =
|
||||
ThemeUtils.getColor(context, R.attr.code_block_bg_color)
|
||||
ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.code_block_bg_color)
|
||||
private fun resolveQuoteBarColor() =
|
||||
ThemeUtils.getColor(context, R.attr.quote_bar_color)
|
||||
ThemeUtils.getColor(context, im.vector.lib.ui.styles.R.attr.quote_bar_color)
|
||||
|
||||
private var codeBlockBackground: Int = resolveCodeBlockBackground()
|
||||
private var quoteBarColor: Int = resolveQuoteBarColor()
|
||||
|
|
|
@ -144,7 +144,7 @@ class LoginFragment :
|
|||
}
|
||||
|
||||
if (error == 0) {
|
||||
loginViewModel.handle(LoginAction.LoginOrRegister(login, password, getString(R.string.login_mobile_device_sc)))
|
||||
loginViewModel.handle(LoginAction.LoginOrRegister(login, password, getString(CommonStrings.login_mobile_device_sc)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.features.login
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -45,6 +46,8 @@ open class PromptSimplifiedModeActivity : VectorBaseActivity<ActivityLoginBindin
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
@SuppressLint("MissingSuperCall")
|
||||
override fun onBackPressed() {
|
||||
// Don't call super - we don't want to quit on back press, user should select a mode
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ class ImageContentRenderer @Inject constructor(
|
|||
.load(imageUrl)
|
||||
.fitCenter()
|
||||
.listener(object: RequestListener<Drawable> {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>, isFirstResource: Boolean): Boolean {
|
||||
Timber.e("Rendering url $imageUrl failed: $e")
|
||||
if (hideOnFail) {
|
||||
imageView.isGone = true
|
||||
|
@ -126,7 +126,7 @@ class ImageContentRenderer @Inject constructor(
|
|||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
|
||||
override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>?, dataSource: DataSource, isFirstResource: Boolean): Boolean {
|
||||
if (hideOnFail) {
|
||||
imageView.isVisible = true
|
||||
}
|
||||
|
@ -162,13 +162,13 @@ class ImageContentRenderer @Inject constructor(
|
|||
|
||||
var request = createGlideRequest(data, mode, imageView, size)
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>, isFirstResource: Boolean): Boolean {
|
||||
Timber.e(e, "Glide image render failed")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
|
||||
if (resource != null /*&& (data.width == null || data.height == null || data.width == 0 || data.height == 0)*/) {
|
||||
override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>?, dataSource: DataSource, isFirstResource: Boolean): Boolean {
|
||||
//if ((data.width == null || data.height == null || data.width == 0 || data.height == 0)) {
|
||||
val updatedData = data.copy(width = resource.intrinsicWidth, height = resource.intrinsicHeight)
|
||||
val newSize = processSize(updatedData, mode)
|
||||
imageView.updateLayoutParams {
|
||||
|
@ -176,7 +176,7 @@ class ImageContentRenderer @Inject constructor(
|
|||
height = newSize.height
|
||||
}
|
||||
onImageSizeListener?.onImageSizeUpdated(newSize.width, newSize.height)
|
||||
}
|
||||
//}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
|
|
@ -946,7 +946,7 @@ class NotificationUtils @Inject constructor(
|
|||
noisy: Boolean,
|
||||
lastMessageTimestamp: Long
|
||||
): Notification {
|
||||
val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color)
|
||||
val accentColor = ContextCompat.getColor(context, im.vector.lib.ui.styles.R.color.notification_accent_color)
|
||||
val smallIcon = R.drawable.ic_status_bar_sc
|
||||
|
||||
return NotificationCompat.Builder(context, if (noisy) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID)
|
||||
|
|
|
@ -117,7 +117,7 @@ class CreatePollController @Inject constructor(
|
|||
genericButtonItem {
|
||||
id("add_option")
|
||||
text(host.stringProvider.getString(CommonStrings.create_poll_add_option))
|
||||
textColor(host.colorProvider.getColorFromAttribute(R.attr.colorAccent))
|
||||
textColor(host.colorProvider.getColorFromAttribute(com.google.android.material.R.attr.colorAccent))
|
||||
gravity(Gravity.START)
|
||||
bold(true)
|
||||
highlight(false)
|
||||
|
|
|
@ -54,9 +54,9 @@ class EmojiSearchResultController @Inject constructor(
|
|||
if (!vectorPreferences.simplifiedMode()) {
|
||||
// Extra EmojiItem to allow reacting with freeform text
|
||||
val freeformReaction = EmojiItem(
|
||||
name = stringProvider.getString(R.string.freeform_react_with, data.query),
|
||||
name = stringProvider.getString(CommonStrings.freeform_react_with, data.query),
|
||||
unicode = "",
|
||||
keywords = listOf(stringProvider.getString(R.string.freeform_reaction_summary))
|
||||
keywords = listOf(stringProvider.getString(CommonStrings.freeform_reaction_summary))
|
||||
)
|
||||
emojiSearchResultItem {
|
||||
id("de.spiritcroc.riotx.freeform-reaction.${data.query}")
|
||||
|
|
|
@ -98,7 +98,7 @@ class CreateRoomController @Inject constructor(
|
|||
|
||||
settingsSectionTitleItem {
|
||||
id("settingsSection")
|
||||
titleResId(R.string.create_room_settings_section)
|
||||
titleResId(CommonStrings.create_room_settings_section)
|
||||
id("visibility")
|
||||
titleResId(CommonStrings.room_settings_room_access_title)
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ class RoomMemberProfileController @Inject constructor(
|
|||
id("verify_footer")
|
||||
text(host.stringProvider.getString(CommonStrings.room_profile_encrypted_subtitle).toEpoxyCharSequence())
|
||||
centered(false)
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_header_background))
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_header_background))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -175,7 +175,7 @@ class RoomMemberProfileController @Inject constructor(
|
|||
id("verify_footer_not_encrypted")
|
||||
text(host.stringProvider.getString(CommonStrings.room_profile_not_encrypted_subtitle).toEpoxyCharSequence())
|
||||
centered(false)
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_header_background))
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_header_background))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ class RoomProfileController @Inject constructor(
|
|||
genericFooterItem {
|
||||
id("e2e info")
|
||||
centered(false)
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_header_background))
|
||||
backgroundColor(host.colorProvider.getColorFromAttribute(im.vector.lib.ui.styles.R.attr.vctr_header_background))
|
||||
text(
|
||||
span {
|
||||
apply {
|
||||
|
|
|
@ -61,10 +61,10 @@ enum class RoomMemberListCategories(@StringRes val titleRes: Int) {
|
|||
USER(CommonStrings.room_member_power_level_users),
|
||||
|
||||
// Singular variants
|
||||
SG_ADMIN(R.string.power_level_admin),
|
||||
SG_MODERATOR(R.string.power_level_moderator),
|
||||
SG_CUSTOM(R.string.power_level_custom_no_value),
|
||||
SG_USER(R.string.power_level_default),
|
||||
SG_ADMIN(CommonStrings.power_level_admin),
|
||||
SG_MODERATOR(CommonStrings.power_level_moderator),
|
||||
SG_CUSTOM(CommonStrings.power_level_custom_no_value),
|
||||
SG_USER(CommonStrings.power_level_default),
|
||||
// Header for unified members
|
||||
MEMBER(R.string.room_member_power_level_users)
|
||||
MEMBER(CommonStrings.room_member_power_level_users)
|
||||
}
|
||||
|
|
|
@ -119,12 +119,12 @@ class VectorSettingsAdvancedSettingsFragment :
|
|||
findPreference<VectorPreference>("SETTINGS_APPLY_SC_DEFAULT_SETTINGS")?.let {
|
||||
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.settings_apply_sc_default_settings_dialog_title)
|
||||
.setMessage(R.string.settings_apply_sc_default_settings_dialog_summary)
|
||||
.setPositiveButton(R.string._continue) { _, _ ->
|
||||
.setTitle(CommonStrings.settings_apply_sc_default_settings_dialog_title)
|
||||
.setMessage(CommonStrings.settings_apply_sc_default_settings_dialog_summary)
|
||||
.setPositiveButton(CommonStrings._continue) { _, _ ->
|
||||
vectorPreferences.applyScDefaultValues()
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel) { _, _ -> /* Just close dialog */ }
|
||||
.setNegativeButton(CommonStrings.action_cancel) { _, _ -> /* Just close dialog */ }
|
||||
.show()
|
||||
true
|
||||
}
|
||||
|
|
|
@ -21,13 +21,14 @@ import de.spiritcroc.preference.ColorMatrixListPreference
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.restart
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import javax.inject.Inject
|
||||
|
||||
class VectorSettingsAdvancedThemeFragment @Inject constructor(
|
||||
//private val vectorPreferences: VectorPreferences
|
||||
) : VectorSettingsBaseFragment() {
|
||||
|
||||
override var titleRes = R.string.settings_advanced_theme_settings
|
||||
override var titleRes = CommonStrings.settings_advanced_theme_settings
|
||||
override val preferenceXmlRes = R.xml.vector_settings_advanced_theme_settings
|
||||
|
||||
override fun bindPref() {
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
package im.vector.app.features.settings
|
||||
|
||||
import im.vector.app.R
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import javax.inject.Inject
|
||||
|
||||
class VectorSettingsBubbleAppearanceFragment @Inject constructor(
|
||||
//private val vectorPreferences: VectorPreferences
|
||||
) : VectorSettingsBaseFragment() {
|
||||
|
||||
override var titleRes = R.string.bubble_appearance
|
||||
override var titleRes = CommonStrings.bubble_appearance
|
||||
override val preferenceXmlRes = R.xml.vector_settings_bubble_appearance
|
||||
|
||||
override fun bindPref() {
|
||||
|
|
|
@ -118,7 +118,7 @@ class VectorSettingsPreferencesFragment :
|
|||
}
|
||||
}
|
||||
if (ThemeUtils.darkThemePossible(requireContext())) {
|
||||
lightThemePref.title = getString(R.string.settings_light_theme)
|
||||
lightThemePref.title = getString(CommonStrings.settings_light_theme)
|
||||
darkThemePref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue is String) {
|
||||
ThemeUtils.setApplicationDarkTheme(requireContext().applicationContext, newValue)
|
||||
|
@ -132,7 +132,7 @@ class VectorSettingsPreferencesFragment :
|
|||
}
|
||||
}
|
||||
} else {
|
||||
lightThemePref.title = getString(R.string.settings_theme)
|
||||
lightThemePref.title = getString(CommonStrings.settings_theme)
|
||||
darkThemePref.parent?.removePreference(darkThemePref)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,14 @@ import androidx.preference.PreferenceGroup
|
|||
import de.spiritcroc.matrixsdk.util.DbgUtil
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.preference.VectorSwitchPreference
|
||||
import im.vector.lib.strings.CommonStrings
|
||||
import javax.inject.Inject
|
||||
|
||||
class VectorSettingsScDebuggingFragment @Inject constructor(
|
||||
//private val vectorPreferences: VectorPreferences
|
||||
) : VectorSettingsBaseFragment() {
|
||||
|
||||
override var titleRes = R.string.settings_sc_debugging
|
||||
override var titleRes = CommonStrings.settings_sc_debugging
|
||||
override val preferenceXmlRes = R.xml.vector_settings_sc_debugging
|
||||
|
||||
companion object {
|
||||
|
@ -22,16 +23,16 @@ class VectorSettingsScDebuggingFragment @Inject constructor(
|
|||
|
||||
data class DbgPref(val key: String, @StringRes val stringRes: Int)
|
||||
private val dbgLoggingPrefs = arrayOf(
|
||||
DbgPref(DbgUtil.DBG_TIMELINE_CHUNKS, R.string.settings_sc_dbg_timeline_chunks),
|
||||
DbgPref(DbgUtil.DBG_READ_MARKER, R.string.settings_sc_dbg_read_marker),
|
||||
DbgPref(DbgUtil.DBG_READ_RECEIPTS, R.string.settings_sc_dbg_read_receipts),
|
||||
DbgPref(DbgUtil.DBG_VIEW_PAGER, R.string.settings_sc_dbg_view_pager),
|
||||
DbgPref(DbgUtil.DBG_TIMELINE_CHUNKS, CommonStrings.settings_sc_dbg_timeline_chunks),
|
||||
DbgPref(DbgUtil.DBG_READ_MARKER, CommonStrings.settings_sc_dbg_read_marker),
|
||||
DbgPref(DbgUtil.DBG_READ_RECEIPTS, CommonStrings.settings_sc_dbg_read_receipts),
|
||||
DbgPref(DbgUtil.DBG_VIEW_PAGER, CommonStrings.settings_sc_dbg_view_pager),
|
||||
)
|
||||
private val dbgVisualsPrefs = arrayOf(
|
||||
DbgPref(DbgUtil.DBG_SHOW_DISPLAY_INDEX, R.string.settings_sc_dbg_show_display_index),
|
||||
DbgPref(DbgUtil.DBG_SHOW_READ_TRACKING, R.string.settings_sc_dbg_show_read_tracking),
|
||||
DbgPref(DbgUtil.DBG_VIEW_PAGER_VISUALS, R.string.settings_sc_dbg_view_pager_visuals),
|
||||
DbgPref(DbgUtil.DBG_SHOW_DUPLICATE_READ_RECEIPTS, R.string.settings_sc_dbg_show_duplicate_read_receipts),
|
||||
DbgPref(DbgUtil.DBG_SHOW_DISPLAY_INDEX, CommonStrings.settings_sc_dbg_show_display_index),
|
||||
DbgPref(DbgUtil.DBG_SHOW_READ_TRACKING, CommonStrings.settings_sc_dbg_show_read_tracking),
|
||||
DbgPref(DbgUtil.DBG_VIEW_PAGER_VISUALS, CommonStrings.settings_sc_dbg_view_pager_visuals),
|
||||
DbgPref(DbgUtil.DBG_SHOW_DUPLICATE_READ_RECEIPTS, CommonStrings.settings_sc_dbg_show_duplicate_read_receipts),
|
||||
)
|
||||
val dbgPrefs = dbgLoggingPrefs + dbgVisualsPrefs
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ class VectorSettingsVoiceVideoFragment : VectorSettingsBaseFragment() {
|
|||
}
|
||||
|
||||
useDefaultStunPreference.let {
|
||||
val stun = getString(R.string.fallback_stun_server_url)
|
||||
it.summary = getString(R.string.settings_call_ringtone_use_default_stun_summary, stun)
|
||||
val stun = getString(im.vector.app.config.R.string.fallback_stun_server_url)
|
||||
it.summary = getString(CommonStrings.settings_call_ringtone_use_default_stun_summary, stun)
|
||||
}
|
||||
|
||||
mCallRingtonePreference.let {
|
||||
|
|
|
@ -143,7 +143,7 @@ data class ScBubbleAppearance(
|
|||
}
|
||||
|
||||
val defaultScBubbleAppearance = ScBubbleAppearance(
|
||||
R.dimen.sc_bubble_radius,
|
||||
im.vector.lib.ui.styles.R.dimen.sc_bubble_radius,
|
||||
R.drawable.msg_bubble_text_outgoing,
|
||||
R.drawable.msg_bubble_text_incoming,
|
||||
R.drawable.msg_bubble_text_outgoing_notail,
|
||||
|
@ -154,7 +154,7 @@ val defaultScBubbleAppearance = ScBubbleAppearance(
|
|||
)
|
||||
|
||||
val r1ScBubbleAppearance = ScBubbleAppearance(
|
||||
R.dimen.sc_bubble_r1_radius,
|
||||
im.vector.lib.ui.styles.R.dimen.sc_bubble_r1_radius,
|
||||
R.drawable.msg_bubble_r1_text_outgoing,
|
||||
R.drawable.msg_bubble_r1_text_incoming,
|
||||
R.drawable.msg_bubble_r1_text_outgoing_notail,
|
||||
|
@ -166,7 +166,7 @@ val r1ScBubbleAppearance = ScBubbleAppearance(
|
|||
|
||||
|
||||
val r2ScBubbleAppearance = ScBubbleAppearance(
|
||||
R.dimen.sc_bubble_r2_radius,
|
||||
im.vector.lib.ui.styles.R.dimen.sc_bubble_r2_radius,
|
||||
R.drawable.msg_bubble_r2_text_outgoing,
|
||||
R.drawable.msg_bubble_r2_text_incoming,
|
||||
R.drawable.msg_bubble_r2_text_outgoing_notail,
|
||||
|
|
|
@ -373,8 +373,8 @@ object ThemeUtils {
|
|||
color.data
|
||||
} catch (e: Exception) {
|
||||
when (colorAttribute) {
|
||||
android.R.attr.colorAccent -> ContextCompat.getColor(c, R.color.accent_sc)
|
||||
R.attr.colorAccent -> ContextCompat.getColor(c, R.color.accent_sc)
|
||||
android.R.attr.colorAccent -> ContextCompat.getColor(c, R.color.accent_sc)
|
||||
com.google.android.material.R.attr.colorAccent -> ContextCompat.getColor(c, R.color.accent_sc)
|
||||
else -> {
|
||||
Timber.e(e, "Unable to get color")
|
||||
ContextCompat.getColor(c, android.R.color.holo_red_dark)
|
||||
|
|
Loading…
Reference in a new issue