From d7c9e15a73129165144a77088129979381de1577 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 Jan 2022 12:01:10 +0100 Subject: [PATCH 1/6] Create EpoxyCharSequence: wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering --- .../epoxy/charsequence/EpoxyCharSequence.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt diff --git a/vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt b/vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt new file mode 100644 index 0000000000..dcd19b598d --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/epoxy/charsequence/EpoxyCharSequence.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.epoxy.charsequence + +/** + * Wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering + */ +class EpoxyCharSequence(val charSequence: CharSequence) { + private val hash = charSequence.toString().hashCode() + + override fun hashCode() = hash + override fun equals(other: Any?) = other is EpoxyCharSequence && other.hash == hash +} From ca44d8f4d802ecdd181023675eef0ff3bbb10840 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 Jan 2022 13:43:41 +0100 Subject: [PATCH 2/6] Use EpoxyCharSequence for all Epoxy items Or use String if possible --- .../BottomSheetMessagePreviewItem.kt | 15 +++--- .../bottomsheet/BottomSheetRadioActionItem.kt | 4 +- .../bottomsheet/BottomSheetSendStateItem.kt | 2 +- .../app/core/epoxy/charsequence/Extensions.kt | 22 ++++++++ .../profiles/notifications/RadioButtonItem.kt | 2 +- .../BottomSheetGenericRadioAction.kt | 2 +- .../ui/list/GenericEmptyWithActionItem.kt | 4 +- .../app/core/ui/list/GenericFooterItem.kt | 2 +- .../im/vector/app/core/ui/list/GenericItem.kt | 9 ++-- .../app/core/ui/list/GenericPillItem.kt | 5 +- .../app/core/ui/list/GenericWithValueItem.kt | 7 +-- .../command/AutocompleteCommandItem.kt | 6 +-- ...eysBackupSettingsRecyclerViewController.kt | 50 +++++++++++-------- .../cancel/VerificationCancelController.kt | 14 ++++-- .../cancel/VerificationNotMeController.kt | 3 +- .../VerificationChooseMethodController.kt | 3 +- .../VerificationConclusionController.kt | 10 ++-- .../emoji/VerificationEmojiCodeController.kt | 5 +- .../BottomSheetVerificationActionItem.kt | 4 +- .../BottomSheetVerificationDecimalCodeItem.kt | 2 +- .../BottomSheetVerificationNoticeItem.kt | 5 +- .../BottomSheetVerificationWaitingItem.kt | 2 +- .../VerificationQRWaitingController.kt | 3 +- .../VerificationQrScannedByOtherController.kt | 5 +- .../request/VerificationRequestController.kt | 5 +- .../devtools/RoomStateListController.kt | 9 ++-- .../app/features/discovery/SettingsItem.kt | 2 +- .../features/form/FormAdvancedToggleItem.kt | 2 +- .../app/features/form/FormSwitchItem.kt | 2 +- .../readreceipts/DisplayReadReceiptItem.kt | 2 +- .../detail/search/SearchResultController.kt | 3 +- .../room/detail/search/SearchResultItem.kt | 5 +- .../action/MessageActionsEpoxyController.kt | 5 +- .../ViewEditHistoryEpoxyController.kt | 7 +-- .../timeline/factory/EncryptedItemFactory.kt | 3 +- .../timeline/factory/MessageItemFactory.kt | 38 +++++++------- .../timeline/factory/NoticeItemFactory.kt | 3 +- .../timeline/factory/RoomCreateItemFactory.kt | 3 +- .../detail/timeline/item/DaySeparatorItem.kt | 2 +- .../room/detail/timeline/item/DefaultItem.kt | 2 +- .../timeline/item/MessageBlockCodeItem.kt | 9 ++-- .../detail/timeline/item/MessageFileItem.kt | 2 +- .../detail/timeline/item/MessageTextItem.kt | 11 ++-- .../room/detail/timeline/item/NoticeItem.kt | 5 +- .../detail/timeline/item/RoomCreateItem.kt | 5 +- .../timeline/item/StatusTileTimelineItem.kt | 4 +- .../timeline/item/WidgetTileTimelineItem.kt | 2 +- .../reactions/ReactionInfoSimpleItem.kt | 9 ++-- .../reactions/ViewReactionsEpoxyController.kt | 3 +- .../home/room/list/RoomCategoryItem.kt | 2 +- .../home/room/list/RoomInvitationItem.kt | 2 +- .../home/room/list/RoomSummaryItem.kt | 13 ++--- .../home/room/list/RoomSummaryItemFactory.kt | 6 +-- .../poll/create/CreatePollController.kt | 5 +- .../createroom/CreateSubSpaceController.kt | 3 +- .../devices/DeviceListEpoxyController.kt | 26 +++++----- .../devices/DeviceTrustInfoEpoxyController.kt | 9 ++-- .../joinrule/RoomJoinRuleRadioAction.kt | 2 +- .../CrossSigningSettingsController.kt | 15 +++--- ...ceVerificationInfoBottomSheetController.kt | 46 ++++++++--------- .../devtools/AccountDataEpoxyController.kt | 3 +- .../GossipingTrailPagedEpoxyController.kt | 11 ++-- .../IncomingKeyRequestPagedController.kt | 5 +- .../OutgoingKeyRequestPagedController.kt | 5 +- .../HomeserverSettingsController.kt | 5 +- .../create/SpaceAdd3pidEpoxyController.kt | 3 +- .../explore/SpaceDirectoryController.kt | 3 +- .../spaces/manage/AddRoomListController.kt | 5 +- .../people/SpacePeopleListController.kt | 5 +- .../app/features/userdirectory/ActionItem.kt | 2 +- .../userdirectory/UserListController.kt | 5 +- 71 files changed, 290 insertions(+), 220 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/epoxy/charsequence/Extensions.kt diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index 46a98e6963..f6088b5eda 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -26,6 +26,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.util.preventMutation import im.vector.app.core.extensions.setTextOrHide @@ -50,13 +51,13 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence? = null + var title: String? = null @StringRes @EpoxyAttribute @@ -47,7 +47,7 @@ abstract class BottomSheetRadioActionItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence? = null + var title: String? = null @StringRes @EpoxyAttribute diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericRadioAction.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericRadioAction.kt index 516612717a..88eaf587a8 100644 --- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericRadioAction.kt +++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericRadioAction.kt @@ -23,7 +23,7 @@ import im.vector.app.core.platform.VectorSharedAction * Parent class for a bottom sheet action */ open class BottomSheetGenericRadioAction( - open val title: CharSequence?, + open val title: String?, open val description: String? = null, open val isSelected: Boolean ) : VectorSharedAction { diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt index 359488e3f4..5801ca6b7c 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericEmptyWithActionItem.kt @@ -39,10 +39,10 @@ import im.vector.app.core.extensions.setTextOrHide abstract class GenericEmptyWithActionItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence? = null + var title: String? = null @EpoxyAttribute - var description: CharSequence? = null + var description: String? = null @EpoxyAttribute @DrawableRes diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt index 8adad00a1a..323c21b76b 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericFooterItem.kt @@ -38,7 +38,7 @@ import im.vector.app.features.themes.ThemeUtils abstract class GenericFooterItem : VectorEpoxyModel() { @EpoxyAttribute - var text: CharSequence? = null + var text: String? = null @EpoxyAttribute var style: ItemStyle = ItemStyle.NORMAL_TEXT diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt index cdfd1d75fc..3a691ddfd5 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericItem.kt @@ -28,6 +28,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide @@ -41,10 +42,10 @@ import im.vector.app.core.extensions.setTextOrHide abstract class GenericItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence? = null + var title: EpoxyCharSequence? = null @EpoxyAttribute - var description: CharSequence? = null + var description: EpoxyCharSequence? = null @EpoxyAttribute var style: ItemStyle = ItemStyle.NORMAL_TEXT @@ -71,7 +72,7 @@ abstract class GenericItem : VectorEpoxyModel() { override fun bind(holder: Holder) { super.bind(holder) - holder.titleText.setTextOrHide(title) + holder.titleText.setTextOrHide(title?.charSequence) if (titleIconResourceId != -1) { holder.titleIcon.setImageResource(titleIconResourceId) @@ -82,7 +83,7 @@ abstract class GenericItem : VectorEpoxyModel() { holder.titleText.textSize = style.toTextSize() - holder.descriptionText.setTextOrHide(description) + holder.descriptionText.setTextOrHide(description?.charSequence) if (hasIndeterminateProcess) { holder.progressBar.isVisible = true diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt index 451b7f086f..e116561ecb 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericPillItem.kt @@ -28,6 +28,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.themes.ThemeUtils @@ -39,7 +40,7 @@ import im.vector.app.features.themes.ThemeUtils abstract class GenericPillItem : VectorEpoxyModel() { @EpoxyAttribute - var text: CharSequence? = null + var text: EpoxyCharSequence? = null @EpoxyAttribute var style: ItemStyle = ItemStyle.NORMAL_TEXT @@ -60,7 +61,7 @@ abstract class GenericPillItem : VectorEpoxyModel() { override fun bind(holder: Holder) { super.bind(holder) - holder.textView.setTextOrHide(text) + holder.textView.setTextOrHide(text?.charSequence) holder.textView.typeface = style.toTypeFace() holder.textView.textSize = style.toTextSize() holder.textView.gravity = if (centered) Gravity.CENTER_HORIZONTAL else Gravity.START diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt index 4ba403fd9a..f95281eb75 100644 --- a/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt +++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericWithValueItem.kt @@ -27,6 +27,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.themes.ThemeUtils @@ -41,10 +42,10 @@ import im.vector.app.features.themes.ThemeUtils abstract class GenericWithValueItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence? = null + var title: EpoxyCharSequence? = null @EpoxyAttribute - var value: CharSequence? = null + var value: String? = null @EpoxyAttribute @ColorInt @@ -62,7 +63,7 @@ abstract class GenericWithValueItem : VectorEpoxyModel() { @EpoxyAttribute - var name: CharSequence? = null + var name: String? = null @EpoxyAttribute - var parameters: CharSequence? = null + var parameters: String? = null @EpoxyAttribute - var description: CharSequence? = null + var description: String? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var clickListener: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt index ea0acd8be8..f007fe44f0 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider @@ -73,11 +74,11 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.Disabled -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_not_setup)) + title(host.stringProvider.getString(R.string.keys_backup_settings_status_not_setup).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup)) + description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } } @@ -88,12 +89,12 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.Enabling -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ko)) + title(host.stringProvider.getString(R.string.keys_backup_settings_status_ko).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup)) + description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { - description(keyBackupState.toString()) + description(keyBackupState.toString().toEpoxyCharSequence()) } endIconResourceId(R.drawable.unit_test_ko) } @@ -103,12 +104,12 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.ReadyToBackUp -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok)) + title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup)) + description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { - description(host.stringProvider.getString(R.string.keys_backup_info_keys_all_backup_up)) + description(host.stringProvider.getString(R.string.keys_backup_info_keys_all_backup_up).toEpoxyCharSequence()) } endIconResourceId(R.drawable.unit_test_ok) } @@ -119,7 +120,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( KeysBackupState.BackingUp -> { genericItem { id("summary") - title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok)) + title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok).toEpoxyCharSequence()) style(ItemStyle.BIG_TEXT) hasIndeterminateProcess(true) @@ -129,10 +130,11 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( val remainingKeysToBackup = totalKeys - backedUpKeys if (data.keysBackupVersionTrust()?.usable == false) { - description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup)) + description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence()) } else { description(host.stringProvider - .getQuantityString(R.plurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup)) + .getQuantityString(R.plurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup) + .toEpoxyCharSequence()) } } @@ -144,14 +146,14 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( // Add infos genericItem { id("version") - title(host.stringProvider.getString(R.string.keys_backup_info_title_version)) - description(keyVersionResult?.version ?: "") + title(host.stringProvider.getString(R.string.keys_backup_info_title_version).toEpoxyCharSequence()) + description(keyVersionResult?.version.orEmpty().toEpoxyCharSequence()) } genericItem { id("algorithm") - title(host.stringProvider.getString(R.string.keys_backup_info_title_algorithm)) - description(keyVersionResult?.algorithm ?: "") + title(host.stringProvider.getString(R.string.keys_backup_info_title_algorithm).toEpoxyCharSequence()) + description(keyVersionResult?.algorithm.orEmpty().toEpoxyCharSequence()) } if (vectorPreferences.developerMode()) { @@ -189,7 +191,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( keysVersionTrust().signatures.forEach { genericItem { id(UUID.randomUUID().toString()) - title(host.stringProvider.getString(R.string.keys_backup_info_title_signature)) + title(host.stringProvider.getString(R.string.keys_backup_info_title_signature).toEpoxyCharSequence()) val isDeviceKnown = it.device != null val isDeviceVerified = it.device?.isVerified ?: false @@ -197,21 +199,23 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( val deviceId: String = it.deviceId ?: "" if (!isDeviceKnown) { - description(host.stringProvider.getString(R.string.keys_backup_settings_signature_from_unknown_device, deviceId)) + description(host.stringProvider.getString(R.string.keys_backup_settings_signature_from_unknown_device, deviceId).toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_warning) } else { if (isSignatureValid) { if (host.session.sessionParams.deviceId == it.deviceId) { - description(host.stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_this_device)) + description(host.stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_this_device).toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_verified) } else { if (isDeviceVerified) { description(host.stringProvider - .getString(R.string.keys_backup_settings_valid_signature_from_verified_device, deviceId)) + .getString(R.string.keys_backup_settings_valid_signature_from_verified_device, deviceId) + .toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_verified) } else { description(host.stringProvider - .getString(R.string.keys_backup_settings_valid_signature_from_unverified_device, deviceId)) + .getString(R.string.keys_backup_settings_valid_signature_from_unverified_device, deviceId) + .toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_warning) } } @@ -220,10 +224,12 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( endIconResourceId(R.drawable.e2e_warning) if (isDeviceVerified) { description(host.stringProvider - .getString(R.string.keys_backup_settings_invalid_signature_from_verified_device, deviceId)) + .getString(R.string.keys_backup_settings_invalid_signature_from_verified_device, deviceId) + .toEpoxyCharSequence()) } else { description(host.stringProvider - .getString(R.string.keys_backup_settings_invalid_signature_from_unverified_device, deviceId)) + .getString(R.string.keys_backup_settings_invalid_signature_from_unverified_device, deviceId) + .toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt index f10aa3421f..05a5bb7238 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationCancelController.kt @@ -20,6 +20,8 @@ import androidx.core.text.toSpannable import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.colorizeMatchingText @@ -49,12 +51,12 @@ class VerificationCancelController @Inject constructor( if (state.currentDeviceCanCrossSign) { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted)) + notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted).toEpoxyCharSequence()) } } else { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted)) + notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted).toEpoxyCharSequence()) } } } else { @@ -63,9 +65,11 @@ class VerificationCancelController @Inject constructor( bottomSheetVerificationNoticeItem { id("notice") notice( - host.stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID) - .toSpannable() - .colorizeMatchingText(otherUserID, host.colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) + EpoxyCharSequence( + host.stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID) + .toSpannable() + .colorizeMatchingText(otherUserID, host.colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)) + ) ) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt index d816f3d134..5b9c82958e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/cancel/VerificationNotMeController.kt @@ -19,6 +19,7 @@ package im.vector.app.features.crypto.verification.cancel import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState @@ -46,7 +47,7 @@ class VerificationNotMeController @Inject constructor( val host = this bottomSheetVerificationNoticeItem { id("notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification))) + notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)).toEpoxyCharSequence()) } bottomSheetDividerItem { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt index 7025343fc6..352c21a156 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodController.kt @@ -19,6 +19,7 @@ package im.vector.app.features.crypto.verification.choose import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem @@ -60,7 +61,7 @@ class VerificationChooseMethodController @Inject constructor( bottomSheetVerificationNoticeItem { id("notice") - notice(scanCodeInstructions) + notice(scanCodeInstructions.toEpoxyCharSequence()) } if (state.otherCanScanQrCode && !state.qrCodeText.isNullOrBlank()) { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt index 1984a70345..1314fd6fec 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt @@ -19,6 +19,7 @@ package im.vector.app.features.crypto.verification.conclusion import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem @@ -53,7 +54,8 @@ class VerificationConclusionController @Inject constructor( id("notice") notice(host.stringProvider.getString( if (state.isSelfVerification) R.string.verification_conclusion_ok_self_notice - else R.string.verification_conclusion_ok_notice)) + else R.string.verification_conclusion_ok_notice) + .toEpoxyCharSequence()) } bottomSheetVerificationBigImageItem { @@ -66,7 +68,7 @@ class VerificationConclusionController @Inject constructor( ConclusionState.WARNING -> { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure)) + notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure).toEpoxyCharSequence()) } bottomSheetVerificationBigImageItem { @@ -76,7 +78,7 @@ class VerificationConclusionController @Inject constructor( bottomSheetVerificationNoticeItem { id("warning_notice") - notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised))) + notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)).toEpoxyCharSequence()) } bottomDone() @@ -84,7 +86,7 @@ class VerificationConclusionController @Inject constructor( ConclusionState.CANCELLED -> { bottomSheetVerificationNoticeItem { id("notice_cancelled") - notice(host.stringProvider.getString(R.string.verify_cancelled_notice)) + notice(host.stringProvider.getString(R.string.verify_cancelled_notice).toEpoxyCharSequence()) } bottomSheetDividerItem { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt index eab53ea954..838f25ddfa 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeController.kt @@ -21,6 +21,7 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Success import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.ColorProvider @@ -64,7 +65,7 @@ class VerificationEmojiCodeController @Inject constructor( is Success -> { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_emoji_notice)) + notice(host.stringProvider.getString(R.string.verification_emoji_notice).toEpoxyCharSequence()) } bottomSheetVerificationEmojisItem { @@ -101,7 +102,7 @@ class VerificationEmojiCodeController @Inject constructor( is Success -> { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_code_notice)) + notice(host.stringProvider.getString(R.string.verification_code_notice).toEpoxyCharSequence()) } bottomSheetVerificationDecimalCodeItem { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt index 093eddb45e..7dc7a31441 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationActionItem.kt @@ -42,10 +42,10 @@ abstract class BottomSheetVerificationActionItem : VectorEpoxyModel() { @EpoxyAttribute - var code: CharSequence = "" + var code: String = "" override fun bind(holder: Holder) { super.bind(holder) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt index 232cdd0f4a..f63459991b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationNoticeItem.kt @@ -22,6 +22,7 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence /** * A action for bottom sheet. @@ -30,11 +31,11 @@ import im.vector.app.core.epoxy.VectorEpoxyModel abstract class BottomSheetVerificationNoticeItem : VectorEpoxyModel() { @EpoxyAttribute - var notice: CharSequence = "" + lateinit var notice: EpoxyCharSequence override fun bind(holder: Holder) { super.bind(holder) - holder.notice.text = notice + holder.notice.text = notice.charSequence } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationWaitingItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationWaitingItem.kt index d8fc928471..46a1dd04a8 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationWaitingItem.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationWaitingItem.kt @@ -30,7 +30,7 @@ import im.vector.app.core.epoxy.VectorEpoxyModel abstract class BottomSheetVerificationWaitingItem : VectorEpoxyModel() { @EpoxyAttribute - var title: CharSequence = "" + var title: String = "" override fun bind(holder: Holder) { super.bind(holder) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt index e7a8058111..cef5994c38 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.crypto.verification.qrconfirmation import com.airbnb.epoxy.EpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationBigImageItem @@ -45,7 +46,7 @@ class VerificationQRWaitingController @Inject constructor( bottomSheetVerificationNoticeItem { id("notice") apply { - notice(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice)) + notice(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice).toEpoxyCharSequence()) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt index f3990842f9..bb21a6ccef 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt @@ -19,6 +19,7 @@ package im.vector.app.features.crypto.verification.qrconfirmation import com.airbnb.epoxy.EpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState @@ -51,10 +52,10 @@ class VerificationQrScannedByOtherController @Inject constructor( id("notice") apply { if (state.isMe) { - notice(host.stringProvider.getString(R.string.qr_code_scanned_self_verif_notice)) + notice(host.stringProvider.getString(R.string.qr_code_scanned_self_verif_notice).toEpoxyCharSequence()) } else { val name = state.otherUserMxItem?.getBestName() ?: "" - notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name)) + notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt index 6440c0032b..d8082865c8 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt @@ -23,6 +23,7 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.colorizeMatchingText @@ -57,7 +58,7 @@ class VerificationRequestController @Inject constructor( if (state.hasAnyOtherSession) { bottomSheetVerificationNoticeItem { id("notice") - notice(host.stringProvider.getString(R.string.verification_open_other_to_verify)) + notice(host.stringProvider.getString(R.string.verification_open_other_to_verify).toEpoxyCharSequence()) } bottomSheetSelfWaitItem { @@ -112,7 +113,7 @@ class VerificationRequestController @Inject constructor( bottomSheetVerificationNoticeItem { id("notice") - notice(styledText) + notice(styledText.toEpoxyCharSequence()) } bottomSheetDividerItem { diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt index 08aa119a1e..ee5ae600ff 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomStateListController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.devtools import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider @@ -48,8 +49,8 @@ class RoomStateListController @Inject constructor( stateEventsGroups.forEach { entry -> genericItem { id(entry.key) - title(entry.key) - description(host.stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size)) + title(entry.key.toEpoxyCharSequence()) + description(host.stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size).toEpoxyCharSequence()) itemClickAction { host.interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key)) } @@ -88,8 +89,8 @@ class RoomStateListController @Inject constructor( text = stateEvent.stateKey.let { "\"$it\"" } textStyle = "normal" } - }) - description(contentJson) + }.toEpoxyCharSequence()) + description(contentJson.toEpoxyCharSequence()) itemClickAction { host.interactionListener?.processAction(RoomDevToolAction.ShowStateEvent(stateEvent)) } diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt index 9726e63d39..1a14b4c9f3 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsItem.kt @@ -43,7 +43,7 @@ abstract class SettingsItem : EpoxyModelWithHolder() { var descriptionResId: Int? = null @EpoxyAttribute - var description: CharSequence? = null + var description: String? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt index 08ed29b4eb..d50b429c97 100644 --- a/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt +++ b/vector/src/main/java/im/vector/app/features/form/FormAdvancedToggleItem.kt @@ -31,7 +31,7 @@ import im.vector.app.features.themes.ThemeUtils @EpoxyModelClass(layout = R.layout.item_form_advanced_toggle) abstract class FormAdvancedToggleItem : VectorEpoxyModel() { - @EpoxyAttribute lateinit var title: CharSequence + @EpoxyAttribute lateinit var title: String @EpoxyAttribute var expanded: Boolean = false @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/form/FormSwitchItem.kt b/vector/src/main/java/im/vector/app/features/form/FormSwitchItem.kt index 4cf09a1ab6..800a90135b 100644 --- a/vector/src/main/java/im/vector/app/features/form/FormSwitchItem.kt +++ b/vector/src/main/java/im/vector/app/features/form/FormSwitchItem.kt @@ -39,7 +39,7 @@ abstract class FormSwitchItem : VectorEpoxyModel() { var switchChecked: Boolean = false @EpoxyAttribute - var title: CharSequence? = null + var title: String? = null @EpoxyAttribute var summary: String? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt index 7a91dae183..9e3cbef1cc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt @@ -34,7 +34,7 @@ import org.matrix.android.sdk.api.util.MatrixItem abstract class DisplayReadReceiptItem : EpoxyModelWithHolder() { @EpoxyAttribute lateinit var matrixItem: MatrixItem - @EpoxyAttribute var timestamp: CharSequence? = null + @EpoxyAttribute var timestamp: String? = null @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var userClicked: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt index 1b4d9faaec..342f1d9562 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt @@ -26,6 +26,7 @@ import com.airbnb.epoxy.VisibilityState import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem import im.vector.app.core.resources.StringProvider @@ -118,7 +119,7 @@ val text = ((event.content?.get("m.new_content") as? Content) ?: event.content)? .id(eventAndSender.event.eventId) .avatarRenderer(avatarRenderer) .formattedDate(dateFormatter.format(event.originServerTs, DateFormatKind.MESSAGE_SIMPLE)) - .spannable(spannable) + .spannable(spannable.toEpoxyCharSequence()) .sender(eventAndSender.sender ?: eventAndSender.event.senderId?.let { session.getRoomMember(it, data.roomId) }?.toMatrixItem()) .listener { listener?.onItemClicked(eventAndSender.event) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt index c0f71ed6cc..9d146792d9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultItem.kt @@ -24,6 +24,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.displayname.getBestName @@ -35,7 +36,7 @@ abstract class SearchResultItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute var formattedDate: String? = null - @EpoxyAttribute lateinit var spannable: CharSequence + @EpoxyAttribute lateinit var spannable: EpoxyCharSequence @EpoxyAttribute var sender: MatrixItem? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null @@ -46,7 +47,7 @@ abstract class SearchResultItem : VectorEpoxyModel() { sender?.let { avatarRenderer.render(it, holder.avatarImageView) } holder.memberNameView.setTextOrHide(sender?.getBestName()) holder.timeView.text = formattedDate - holder.contentView.text = spannable + holder.contentView.text = spannable.charSequence } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index 3826c4cbad..15f33db6ff 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -27,6 +27,7 @@ import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetMessagePreviewItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetQuickReactionsItem import im.vector.app.core.epoxy.bottomsheet.bottomSheetSendStateItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.DimensionConverter @@ -77,8 +78,8 @@ class MessageActionsEpoxyController @Inject constructor( data(state.timelineEvent()?.buildImageContentRendererData(host.dimensionConverter.dpToPx(66))) userClicked { host.listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) } bindingOptions(bindingOptions) - body(body) - bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)) + body(body.toEpoxyCharSequence()) + bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)?.toEpoxyCharSequence()) time(formattedDate) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt index ed9f831018..96d139f11d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt @@ -23,6 +23,7 @@ import com.airbnb.mvrx.Success import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem @@ -75,7 +76,7 @@ class ViewEditHistoryEpoxyController @Inject constructor( if (sourceEvents.isEmpty()) { genericItem { id("footer") - title(host.stringProvider.getString(R.string.no_message_edits_found)) + title(host.stringProvider.getString(R.string.no_message_edits_found).toEpoxyCharSequence()) } } else { var lastDate: Calendar? = null @@ -133,8 +134,8 @@ class ViewEditHistoryEpoxyController @Inject constructor( } genericItem { id(timelineEvent.eventId) - title(host.dateFormatter.format(timelineEvent.originServerTs, DateFormatKind.EDIT_HISTORY_ROW)) - description(spannedDiff ?: body) + title(host.dateFormatter.format(timelineEvent.originServerTs, DateFormatKind.EDIT_HISTORY_ROW).toEpoxyCharSequence()) + description((spannedDiff ?: body).toEpoxyCharSequence()) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt index 662846704c..b8d7d96ecf 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt @@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.DrawableProvider import im.vector.app.core.resources.StringProvider @@ -110,7 +111,7 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat .leftGuideline(avatarSizeProvider.leftGuideline) .highlighted(params.isHighlighted) .attributes(attributes) - .message(spannableStr) + .message(spannableStr.toEpoxyCharSequence()) .movementMethod(createLinkMovementMethod(params.callback)) } else -> null diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 28b2d98909..e0d6e46084 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -28,6 +28,7 @@ import dagger.Lazy import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider @@ -501,14 +502,14 @@ class MessageItemFactory @Inject constructor( val bindingOptions = spanUtils.getBindingOptions(body) val linkifiedBody = body.linkify(callback) - return MessageTextItem_().apply { - if (informationData.hasBeenEdited) { - val spannable = annotateWithEdited(linkifiedBody, callback, informationData) - message(spannable) - } else { - message(linkifiedBody) - } - } + return MessageTextItem_() + .message( + if (informationData.hasBeenEdited) { + annotateWithEdited(linkifiedBody, callback, informationData) + } else { + linkifiedBody + }.toEpoxyCharSequence() + ) .useBigFont(linkifiedBody.length <= MAX_NUMBER_OF_EMOJI_FOR_BIG_FONT * 2 && containsOnlyEmojis(linkifiedBody.toString())) .bindingOptions(bindingOptions) .searchForPills(isFormatted) @@ -530,13 +531,13 @@ class MessageItemFactory @Inject constructor( .apply { if (informationData.hasBeenEdited) { val spannable = annotateWithEdited("", callback, informationData) - editedSpan(spannable) + editedSpan(spannable.toEpoxyCharSequence()) } } .leftGuideline(avatarSizeProvider.leftGuideline) .attributes(attributes) .highlighted(highlight) - .message(formattedBody) + .message(formattedBody.toEpoxyCharSequence()) } private fun annotateWithEdited(linkifiedBody: CharSequence, @@ -599,7 +600,7 @@ class MessageItemFactory @Inject constructor( .imageContentRenderer(imageContentRenderer) .previewUrlCallback(callback) .attributes(attributes) - .message(message) + .message(message.toEpoxyCharSequence()) .bindingOptions(bindingOptions) .highlighted(highlight) .movementMethod(createLinkMovementMethod(callback)) @@ -617,14 +618,13 @@ class MessageItemFactory @Inject constructor( val message = formattedBody.linkify(callback) return MessageTextItem_() - .apply { - if (informationData.hasBeenEdited) { - val spannable = annotateWithEdited(message, callback, informationData) - message(spannable) - } else { - message(message) - } - } + .message( + if (informationData.hasBeenEdited) { + annotateWithEdited(message, callback, informationData) + } else { + message + }.toEpoxyCharSequence() + ) .bindingOptions(bindingOptions) .leftGuideline(avatarSizeProvider.leftGuideline) .previewUrlRetriever(callback?.getPreviewUrlRetriever()) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt index ed6620dcd4..70c8fa7574 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/NoticeItemFactory.kt @@ -16,6 +16,7 @@ package im.vector.app.features.home.room.detail.timeline.factory +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.format.NoticeEventFormatter import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider @@ -37,7 +38,7 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv val attributes = NoticeItem.Attributes( avatarRenderer = avatarRenderer, informationData = informationData, - noticeText = formattedText, + noticeText = EpoxyCharSequence(formattedText), itemLongClickListener = { view -> params.callback?.onEventLongClicked(informationData, null, view) ?: false }, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt index 523fb8e682..3a3d269058 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/RoomCreateItemFactory.kt @@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.features.home.room.detail.timeline.item.RoomCreateItem_ @@ -46,7 +47,7 @@ class RoomCreateItemFactory @Inject constructor(private val stringProvider: Stri } } return RoomCreateItem_() - .text(text) + .text(text.toEpoxyCharSequence()) } private fun defaultRendering(params: TimelineItemFactoryParams): VectorEpoxyModel<*>? { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DaySeparatorItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DaySeparatorItem.kt index c63ec36205..4c9664e612 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DaySeparatorItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DaySeparatorItem.kt @@ -26,7 +26,7 @@ import im.vector.app.core.epoxy.VectorEpoxyHolder @EpoxyModelClass(layout = R.layout.item_timeline_event_day_separator) abstract class DaySeparatorItem : EpoxyModelWithHolder() { - @EpoxyAttribute lateinit var formattedDay: CharSequence + @EpoxyAttribute lateinit var formattedDay: String override fun bind(holder: Holder) { super.bind(holder) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DefaultItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DefaultItem.kt index e6c6e1d372..9d0a3b9a9c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DefaultItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/DefaultItem.kt @@ -56,7 +56,7 @@ abstract class DefaultItem : BaseEventItem() { data class Attributes( val avatarRenderer: AvatarRenderer, val informationData: MessageInformationData, - val text: CharSequence, + val text: String, val itemLongClickListener: View.OnLongClickListener? = null ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt index 3f6add5699..be9b727017 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageBlockCodeItem.kt @@ -20,6 +20,7 @@ import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import me.saket.bettermovementmethod.BetterLinkMovementMethod @@ -28,19 +29,19 @@ import me.saket.bettermovementmethod.BetterLinkMovementMethod abstract class MessageBlockCodeItem : AbsMessageItem() { @EpoxyAttribute - var message: CharSequence? = null + var message: EpoxyCharSequence? = null @EpoxyAttribute - var editedSpan: CharSequence? = null + var editedSpan: EpoxyCharSequence? = null override fun bind(holder: Holder) { super.bind(holder) - holder.messageView.text = message + holder.messageView.text = message?.charSequence renderSendState(holder.messageView, holder.messageView) holder.messageView.onClick(attributes.itemClickListener) holder.messageView.setOnLongClickListener(attributes.itemLongClickListener) holder.editedView.movementMethod = BetterLinkMovementMethod.getInstance() - holder.editedView.setTextOrHide(editedSpan) + holder.editedView.setTextOrHide(editedSpan?.charSequence) } override fun getViewType() = STUB_ID diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt index 9893a1f5bc..b15f909b79 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt @@ -34,7 +34,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStat abstract class MessageFileItem : AbsMessageItem() { @EpoxyAttribute - var filename: CharSequence = "" + var filename: String = "" @EpoxyAttribute var mxcUrl: String = "" diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt index 276008f09e..db7a4ff683 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt @@ -24,6 +24,7 @@ import androidx.core.widget.TextViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.onLongClickIgnoringLinks import im.vector.app.core.epoxy.util.preventMutation @@ -42,7 +43,7 @@ abstract class MessageTextItem : AbsMessageItem() { var searchForPills: Boolean = false @EpoxyAttribute - var message: CharSequence? = null + var message: EpoxyCharSequence? = null @EpoxyAttribute var bindingOptions: BindingOptions? = null @@ -82,14 +83,14 @@ abstract class MessageTextItem : AbsMessageItem() { holder.messageView.textSize = 14F } if (searchForPills) { - message?.findPillsAndProcess(coroutineScope) { + message?.charSequence?.findPillsAndProcess(coroutineScope) { // mmm.. not sure this is so safe in regards to cell reuse it.bind(holder.messageView) } } val textFuture = if (bindingOptions?.canUseTextFuture.orFalse()) { PrecomputedTextCompat.getTextFuture( - message ?: "", + message?.charSequence ?: "", TextViewCompat.getTextMetricsParams(holder.messageView), null) } else { @@ -105,9 +106,9 @@ abstract class MessageTextItem : AbsMessageItem() { holder.messageView.setTextFuture(textFuture) } else { holder.messageView.text = if (bindingOptions?.preventMutation.orFalse()) { - message.preventMutation() + message?.charSequence.preventMutation() } else { - message + message?.charSequence } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt index 4876e8e500..2851668df5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt @@ -23,6 +23,7 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.features.home.AvatarRenderer @@ -37,7 +38,7 @@ abstract class NoticeItem : BaseEventItem() { override fun bind(holder: Holder) { super.bind(holder) - holder.noticeTextView.text = attributes.noticeText + holder.noticeTextView.text = attributes.noticeText.charSequence attributes.avatarRenderer.render(attributes.informationData.matrixItem, holder.avatarImageView) holder.view.setOnLongClickListener(attributes.itemLongClickListener) holder.avatarImageView.onClick(attributes.avatarClickListener) @@ -74,7 +75,7 @@ abstract class NoticeItem : BaseEventItem() { data class Attributes( val avatarRenderer: AvatarRenderer, val informationData: MessageInformationData, - val noticeText: CharSequence, + val noticeText: EpoxyCharSequence, val itemLongClickListener: View.OnLongClickListener? = null, val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null, val avatarClickListener: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt index 8ad3bb0cf0..34edcfe9f4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/RoomCreateItem.kt @@ -22,17 +22,18 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import me.saket.bettermovementmethod.BetterLinkMovementMethod @EpoxyModelClass(layout = R.layout.item_timeline_event_create) abstract class RoomCreateItem : VectorEpoxyModel() { - @EpoxyAttribute lateinit var text: CharSequence + @EpoxyAttribute lateinit var text: EpoxyCharSequence override fun bind(holder: Holder) { super.bind(holder) holder.description.movementMethod = BetterLinkMovementMethod.getInstance() - holder.description.text = text + holder.description.text = text.charSequence } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt index c76e2b230a..6531efb82d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/StatusTileTimelineItem.kt @@ -83,8 +83,8 @@ abstract class StatusTileTimelineItem : AbsBaseMessageItem() { @EpoxyAttribute - lateinit var reactionKey: CharSequence + lateinit var reactionKey: EpoxyCharSequence @EpoxyAttribute - lateinit var authorDisplayName: CharSequence + lateinit var authorDisplayName: String @EpoxyAttribute - var timeStamp: CharSequence? = null + var timeStamp: String? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var userClicked: ClickListener? = null override fun bind(holder: Holder) { super.bind(holder) - holder.emojiReactionView.text = reactionKey.preventMutation() + holder.emojiReactionView.text = reactionKey.charSequence.preventMutation() holder.displayNameView.text = authorDisplayName timeStamp?.let { holder.timeStampView.text = it diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt index 0031cf9feb..0cdb31a8fd 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ViewReactionsEpoxyController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success import im.vector.app.EmojiSpanify import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericLoaderItem @@ -56,7 +57,7 @@ class ViewReactionsEpoxyController @Inject constructor( reactionInfoSimpleItem { id(reactionInfo.eventId) timeStamp(reactionInfo.timestamp) - reactionKey(host.emojiSpanify.spanify(reactionInfo.reactionKey)) + reactionKey(host.emojiSpanify.spanify(reactionInfo.reactionKey).toEpoxyCharSequence()) authorDisplayName(reactionInfo.authorName ?: reactionInfo.authorId) userClicked { host.listener?.didSelectUser(reactionInfo.authorId) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt index 5840870d46..bec3ccc643 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt @@ -32,7 +32,7 @@ import im.vector.app.features.themes.ThemeUtils @EpoxyModelClass(layout = R.layout.item_room_category) abstract class RoomCategoryItem : VectorEpoxyModel() { - @EpoxyAttribute lateinit var title: CharSequence + @EpoxyAttribute lateinit var title: String @EpoxyAttribute var expanded: Boolean = false @EpoxyAttribute var unreadNotificationCount: Int = 0 @EpoxyAttribute var showHighlighted: Boolean = false diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomInvitationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomInvitationItem.kt index 4413776636..28cc9a9bd0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomInvitationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomInvitationItem.kt @@ -39,7 +39,7 @@ abstract class RoomInvitationItem : VectorEpoxyModel( @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute lateinit var matrixItem: MatrixItem - @EpoxyAttribute var secondLine: CharSequence? = null + @EpoxyAttribute var secondLine: String? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null @EpoxyAttribute lateinit var changeMembershipState: ChangeMembershipState @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var acceptListener: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index fd0ccd17e9..4261acd7ee 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -30,6 +30,7 @@ import im.vector.app.R 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.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.ui.views.PresenceStateImageView @@ -44,16 +45,12 @@ import org.matrix.android.sdk.api.util.MatrixItem @EpoxyModelClass(layout = R.layout.item_room) abstract class RoomSummaryItem : VectorEpoxyModel() { - @EpoxyAttribute lateinit var typingMessage: CharSequence + @EpoxyAttribute lateinit var typingMessage: String @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute lateinit var matrixItem: MatrixItem - // Used only for diff calculation - @EpoxyAttribute lateinit var lastEvent: String - - // We use DoNotHash here as Spans are not implementing equals/hashcode - @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) lateinit var lastFormattedEvent: CharSequence - @EpoxyAttribute lateinit var lastEventTime: CharSequence + @EpoxyAttribute lateinit var lastFormattedEvent: EpoxyCharSequence + @EpoxyAttribute lateinit var lastEventTime: String @EpoxyAttribute var encryptionTrustLevel: RoomEncryptionTrustLevel? = null @EpoxyAttribute var userPresence: UserPresence? = null @EpoxyAttribute var showPresence: Boolean = false @@ -76,7 +73,7 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { } holder.titleView.text = matrixItem.getBestName() holder.lastEventTimeView.text = lastEventTime - holder.lastEventView.text = lastFormattedEvent + holder.lastEventView.text = lastFormattedEvent.charSequence holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadIndentIndicator.isVisible = hasUnreadMessage holder.draftView.isVisible = hasDraft diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index fdb7d3a323..bf289c2e7d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -23,6 +23,7 @@ import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer @@ -111,7 +112,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor val showHighlighted = roomSummary.highlightCount > 0 val showSelected = selectedRoomIds.contains(roomSummary.roomId) var latestFormattedEvent: CharSequence = "" - var latestEventTime: CharSequence = "" + var latestEventTime = "" val latestEvent = roomSummary.latestPreviewableEvent if (latestEvent != null) { latestFormattedEvent = displayableEventFormatter.format(latestEvent, roomSummary.isDirect, roomSummary.isDirect.not()) @@ -129,8 +130,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor .matrixItem(roomSummary.toMatrixItem()) .lastEventTime(latestEventTime) .typingMessage(typingMessage) - .lastEvent(latestFormattedEvent.toString()) - .lastFormattedEvent(latestFormattedEvent) + .lastFormattedEvent(latestFormattedEvent.toEpoxyCharSequence()) .showHighlighted(showHighlighted) .showSelected(showSelected) .hasFailedSending(roomSummary.hasFailedSending) diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt index 94a3d0c7d3..90128d9263 100644 --- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt +++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollController.kt @@ -20,6 +20,7 @@ import android.view.Gravity import android.view.inputmethod.EditorInfo import com.airbnb.epoxy.EpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -49,7 +50,7 @@ class CreatePollController @Inject constructor( genericItem { id("question_title") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.create_poll_question_title)) + title(host.stringProvider.getString(R.string.create_poll_question_title).toEpoxyCharSequence()) } val questionImeAction = if (currentState.options.isEmpty()) EditorInfo.IME_ACTION_DONE else EditorInfo.IME_ACTION_NEXT @@ -69,7 +70,7 @@ class CreatePollController @Inject constructor( genericItem { id("options_title") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.create_poll_options_title)) + title(host.stringProvider.getString(R.string.create_poll_options_title).toEpoxyCharSequence()) } currentState.options.forEachIndexed { index, option -> diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt index 26ea2f30a3..c8d907b0b2 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateSubSpaceController.kt @@ -20,6 +20,7 @@ import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericPillItem @@ -52,7 +53,7 @@ class CreateSubSpaceController @Inject constructor( id("beta") imageRes(R.drawable.ic_beta_pill) tintIcon(false) - text(host.stringProvider.getString(R.string.space_add_space_to_any_space_you_manage)) + text(host.stringProvider.getString(R.string.space_add_space_to_any_space_you_manage).toEpoxyCharSequence()) } formEditableSquareAvatarItem { diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt index 0325cb132e..83a4e614ec 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.ColorProvider @@ -40,7 +41,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: private val colorProvider: ColorProvider, private val dimensionConverter: DimensionConverter, private val vectorPreferences: VectorPreferences) : - TypedEpoxyController() { + TypedEpoxyController() { interface InteractionListener { fun onDeviceSelected(device: CryptoDeviceInfo) @@ -75,11 +76,11 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: style(ItemStyle.BIG_TEXT) titleIconResourceId(if (allGreen) R.drawable.ic_shield_trusted else R.drawable.ic_shield_warning) title( - host.stringProvider.getString( - if (allGreen) R.string.verification_profile_verified else R.string.verification_profile_warning - ) + host.stringProvider + .getString(if (allGreen) R.string.verification_profile_verified else R.string.verification_profile_warning) + .toEpoxyCharSequence() ) - description(host.stringProvider.getString(R.string.verification_conclusion_ok_notice)) + description(host.stringProvider.getString(R.string.verification_conclusion_ok_notice).toEpoxyCharSequence()) } if (vectorPreferences.developerMode()) { @@ -90,7 +91,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: genericItem { id("sessions") style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.room_member_profile_sessions_section_title)) + title(host.stringProvider.getString(R.string.room_member_profile_sessions_section_title).toEpoxyCharSequence()) } if (deviceList.isEmpty()) { // Can this really happen? @@ -105,7 +106,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: id(device.deviceId) titleIconResourceId(if (device.isVerified) R.drawable.ic_shield_trusted else R.drawable.ic_shield_warning) apply { - if (host.vectorPreferences.developerMode()) { + val title = if (host.vectorPreferences.developerMode()) { val seq = span { +(device.displayName() ?: device.deviceId) +"\n" @@ -115,10 +116,11 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: textSize = host.dimensionConverter.spToPx(14) } } - title(seq) + seq } else { - title(device.displayName() ?: device.deviceId) + device.displayName() ?: device.deviceId } + title(title.toEpoxyCharSequence()) } value( host.stringProvider.getString( @@ -163,7 +165,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } @@ -179,7 +181,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } @@ -195,7 +197,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider: textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt index bce219a711..c700842c19 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.roommemberprofile.devices import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -52,9 +53,9 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi style(ItemStyle.BIG_TEXT) titleIconResourceId(if (isVerified) R.drawable.ic_shield_trusted else R.drawable.ic_shield_warning) title( - host.stringProvider.getString( - if (isVerified) R.string.verification_profile_verified else R.string.verification_profile_warning - ) + host.stringProvider + .getString(if (isVerified) R.string.verification_profile_verified else R.string.verification_profile_warning) + .toEpoxyCharSequence() ) } genericFooterItem { @@ -88,7 +89,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(14) } - } + }.toEpoxyCharSequence() ) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleRadioAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleRadioAction.kt index cdeb49f9ef..608d5489e0 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleRadioAction.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleRadioAction.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules class RoomJoinRuleRadioAction( val roomJoinRule: RoomJoinRules, - title: CharSequence, + title: String, description: String, isSelected: Boolean ) : BottomSheetGenericRadioAction( diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt index 649321474a..d00cb783c9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsController.kt @@ -17,6 +17,7 @@ package im.vector.app.features.settings.crosssigning import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericButtonItem @@ -47,7 +48,7 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("can") titleIconResourceId(R.drawable.ic_shield_trusted) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_complete)) + title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_complete).toEpoxyCharSequence()) } genericButtonItem { id("Reset") @@ -61,7 +62,7 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("trusted") titleIconResourceId(R.drawable.ic_shield_custom) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted)) + title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted).toEpoxyCharSequence()) } genericButtonItem { id("Reset") @@ -75,7 +76,7 @@ class CrossSigningSettingsController @Inject constructor( genericItem { id("enable") titleIconResourceId(R.drawable.ic_shield_black) - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted)) + title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted).toEpoxyCharSequence()) } genericButtonItem { id("Reset") @@ -88,7 +89,7 @@ class CrossSigningSettingsController @Inject constructor( else -> { genericItem { id("not") - title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled)) + title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled).toEpoxyCharSequence()) } genericPositiveButtonItem { @@ -115,7 +116,7 @@ class CrossSigningSettingsController @Inject constructor( textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } @@ -131,7 +132,7 @@ class CrossSigningSettingsController @Inject constructor( textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } @@ -147,7 +148,7 @@ class CrossSigningSettingsController @Inject constructor( textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) textSize = host.dimensionConverter.spToPx(12) } - } + }.toEpoxyCharSequence() ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt index c109920cd6..22e1e67aa4 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.settings.devices import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R import im.vector.app.core.epoxy.bottomSheetDividerItem +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider @@ -34,7 +35,7 @@ import javax.inject.Inject class DeviceVerificationInfoBottomSheetController @Inject constructor( private val stringProvider: StringProvider, private val colorProvider: ColorProvider) : - TypedEpoxyController() { + TypedEpoxyController() { var callback: Callback? = null @@ -88,8 +89,8 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified)) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc)) + title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else if (data.canVerifySession) { // You need to complete security, only if there are other session(s) available, or if 4S contains secrets @@ -97,12 +98,11 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.crosssigning_verify_this_session)) - if (data.hasOtherSessions) { - description(host.stringProvider.getString(R.string.confirm_your_identity)) - } else { - description(host.stringProvider.getString(R.string.confirm_your_identity_quad_s)) - } + title(host.stringProvider.getString(R.string.crosssigning_verify_this_session).toEpoxyCharSequence()) + description(host.stringProvider + .getString(if (data.hasOtherSessions) R.string.confirm_your_identity else R.string.confirm_your_identity_quad_s) + .toEpoxyCharSequence() + ) } } } else { @@ -117,16 +117,16 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified)) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc)) + title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else { genericItem { id("trust${cryptoDeviceInfo.deviceId}") titleIconResourceId(shield) style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.encryption_information_not_verified)) - description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc)) + title(host.stringProvider.getString(R.string.encryption_information_not_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) } } } @@ -135,8 +135,8 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( // DEVICE INFO SECTION genericItem { id("info${cryptoDeviceInfo.deviceId}") - title(cryptoDeviceInfo.displayName() ?: "") - description("(${cryptoDeviceInfo.deviceId})") + title(cryptoDeviceInfo.displayName().orEmpty().toEpoxyCharSequence()) + description("(${cryptoDeviceInfo.deviceId})".toEpoxyCharSequence()) } if (isMine && !currentSessionIsTrusted && data.canVerifySession) { @@ -176,24 +176,24 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( id("trust${cryptoDeviceInfo.deviceId}") style(ItemStyle.BIG_TEXT) titleIconResourceId(shield) - title(host.stringProvider.getString(R.string.encryption_information_verified)) - description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc)) + title(host.stringProvider.getString(R.string.encryption_information_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc).toEpoxyCharSequence()) } } else { genericItem { id("trust${cryptoDeviceInfo.deviceId}") titleIconResourceId(shield) style(ItemStyle.BIG_TEXT) - title(host.stringProvider.getString(R.string.encryption_information_not_verified)) - description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc)) + title(host.stringProvider.getString(R.string.encryption_information_not_verified).toEpoxyCharSequence()) + description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc).toEpoxyCharSequence()) } } // DEVICE INFO SECTION genericItem { id("info${cryptoDeviceInfo.deviceId}") - title(cryptoDeviceInfo.displayName() ?: "") - description("(${cryptoDeviceInfo.deviceId})") + title(cryptoDeviceInfo.displayName().orEmpty().toEpoxyCharSequence()) + description("(${cryptoDeviceInfo.deviceId})".toEpoxyCharSequence()) } // ACTIONS @@ -287,8 +287,8 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor( val info = data.deviceInfo.invoke() ?: return genericItem { id("info${info.deviceId}") - title(info.displayName ?: "") - description("(${info.deviceId})") + title(info.displayName.orEmpty().toEpoxyCharSequence()) + description("(${info.deviceId})".toEpoxyCharSequence()) } genericFooterItem { diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt index 5f0004c0de..77ef13c2f1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem @@ -67,7 +68,7 @@ class AccountDataEpoxyController @Inject constructor( dataList.forEach { accountData -> genericWithValueItem { id(accountData.type) - title(accountData.type) + title(accountData.type.toEpoxyCharSequence()) itemClickAction { host.interactionListener?.didTap(accountData) } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt index 86f64c6b77..08d0d60909 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt @@ -21,8 +21,8 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.R import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider -import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import me.gujun.android.span.span @@ -38,7 +38,6 @@ import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest import javax.inject.Inject class GossipingTrailPagedEpoxyController @Inject constructor( - private val stringProvider: StringProvider, private val vectorDateFormatter: VectorDateFormatter, private val colorProvider: ColorProvider ) : PagedListEpoxyController( @@ -63,7 +62,7 @@ class GossipingTrailPagedEpoxyController @Inject constructor( "${event.getClearType()} [encrypted]" } else { event.type - } + }?.toEpoxyCharSequence() ) description( span { @@ -157,11 +156,11 @@ class GossipingTrailPagedEpoxyController @Inject constructor( +"${content?.requestingDeviceId}" } else if (event.getClearType() == EventType.ENCRYPTED) { span("**Failed to Decrypt** ${event.mCryptoError}") { - textColor = host.colorProvider.getColorFromAttribute(R.attr.colorError) - } + textColor = host.colorProvider.getColorFromAttribute(R.attr.colorError) + } } } - } + }.toEpoxyCharSequence() ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt index 3c90a45237..1e13fa37bb 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt @@ -20,6 +20,7 @@ import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import me.gujun.android.span.span @@ -45,7 +46,7 @@ class IncomingKeyRequestPagedController @Inject constructor( return GenericItem_().apply { id(roomKeyRequest.requestId) - title(roomKeyRequest.requestId) + title(roomKeyRequest.requestId?.toEpoxyCharSequence()) description( span { span("From: ") { @@ -65,7 +66,7 @@ class IncomingKeyRequestPagedController @Inject constructor( textStyle = "bold" } +roomKeyRequest.state.name - } + }.toEpoxyCharSequence() ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt index c2a3bc9827..5d89bf9b1c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.settings.devtools import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import me.gujun.android.span.span @@ -40,7 +41,7 @@ class OutgoingKeyRequestPagedController @Inject constructor() : PagedListEpoxyCo return GenericItem_().apply { id(roomKeyRequest.requestId) - title(roomKeyRequest.requestId) + title(roomKeyRequest.requestId.toEpoxyCharSequence()) description( span { span("roomId: ") { @@ -56,7 +57,7 @@ class OutgoingKeyRequestPagedController @Inject constructor() : PagedListEpoxyCo textStyle = "bold" } +roomKeyRequest.state.name - } + }.toEpoxyCharSequence() ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt index cf623d9d9f..d2ec53523c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/homeserver/HomeserverSettingsController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -143,14 +144,14 @@ class HomeserverSettingsController @Inject constructor( genericWithValueItem { id("room_version_default") - title(host.stringProvider.getString(R.string.settings_server_default_room_version)) + title(host.stringProvider.getString(R.string.settings_server_default_room_version).toEpoxyCharSequence()) value(roomCapabilities.defaultRoomVersion) } roomCapabilities.supportedVersion.forEach { genericWithValueItem { id("room_version_${it.version}") - title(it.version) + title(it.version.toEpoxyCharSequence()) value( host.stringProvider.getString( when (it.status) { diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt index 05d8a78b30..7e1902aac0 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/SpaceAdd3pidEpoxyController.kt @@ -20,6 +20,7 @@ import android.text.InputType import com.airbnb.epoxy.TypedEpoxyController import com.google.android.material.textfield.TextInputLayout import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.ItemStyle @@ -57,7 +58,7 @@ class SpaceAdd3pidEpoxyController @Inject constructor( genericPillItem { id("no_IDS") imageRes(R.drawable.ic_baseline_perm_contact_calendar_24) - text(host.stringProvider.getString(R.string.create_space_identity_server_info_none)) + text(host.stringProvider.getString(R.string.create_space_identity_server_info_none).toEpoxyCharSequence()) } genericButtonItem { id("Discover_Settings") diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt index 4aa4256857..977294f495 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryController.kt @@ -24,6 +24,7 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Uninitialized import im.vector.app.R import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter @@ -87,7 +88,7 @@ class SpaceDirectoryController @Inject constructor( span(host.stringProvider.getString(R.string.spaces_no_server_support_description)) { textColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary) } - } + }.toEpoxyCharSequence() ) } } else { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt index 15103dd870..ec88e9f8a6 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt @@ -20,6 +20,7 @@ import androidx.recyclerview.widget.DiffUtil import com.airbnb.epoxy.EpoxyModel import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.ui.list.GenericPillItem_ import im.vector.app.core.utils.createUIHandler import im.vector.app.features.home.AvatarRenderer @@ -56,7 +57,7 @@ class AddRoomListController @Inject constructor( var listener: Listener? = null var ignoreRooms: List? = null - var subHeaderText: CharSequence? = null + var subHeaderText: String? = null var initialLoadOccurred = false @@ -130,7 +131,7 @@ class AddRoomListController @Inject constructor( add( GenericPillItem_().apply { id("sub_header") - text(host.subHeaderText) + text(host.subHeaderText?.toEpoxyCharSequence()) imageRes(R.drawable.ic_info) } ) diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt index 86d8e12ef6..62bd866cb1 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleListController.kt @@ -18,6 +18,7 @@ package im.vector.app.features.spaces.people import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.profiles.profileMatrixItemWithPowerLevel @@ -128,7 +129,7 @@ class SpacePeopleListController @Inject constructor( span { +"\n" +host.stringProvider.getString(R.string.no_result_placeholder) - } + }.toEpoxyCharSequence() ) description( span { @@ -138,7 +139,7 @@ class SpacePeopleListController @Inject constructor( textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) textStyle = "bold" } - } + }.toEpoxyCharSequence() ) itemClickAction { host.listener?.onInviteToSpaceSelected() diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/ActionItem.kt b/vector/src/main/java/im/vector/app/features/userdirectory/ActionItem.kt index 22f9225522..a4c71c8cb9 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/ActionItem.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/ActionItem.kt @@ -31,7 +31,7 @@ import im.vector.app.core.extensions.setTextOrHide @EpoxyModelClass(layout = R.layout.item_contact_action) abstract class ActionItem : VectorEpoxyModel() { - @EpoxyAttribute var title: CharSequence? = null + @EpoxyAttribute var title: String? = null @EpoxyAttribute @DrawableRes var actionIconRes: Int? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var clickAction: ClickListener? = null diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt index 2028e59073..cb0ec7c36b 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import im.vector.app.R +import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.noResultItem @@ -154,7 +155,7 @@ class UserListController @Inject constructor(private val session: Session, textStyle = "bold" textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) } - } + }.toEpoxyCharSequence() ) itemClickAction { host.callback?.giveIdentityServerConsent() @@ -182,7 +183,7 @@ class UserListController @Inject constructor(private val session: Session, textStyle = "bold" textColor = host.colorProvider.getColorFromAttribute(R.attr.colorPrimary) } - } + }.toEpoxyCharSequence() ) itemClickAction { host.callback?.onSetupDiscovery() From 27161bf7941dc3d62d210b5b3a3a1e7ba4a6dd4d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 Jan 2022 14:17:29 +0100 Subject: [PATCH 3/6] preventMutation is not needed anymore, since we now uses EpoxyCharSequence --- .../vector/app/features/html/SpanUtilsTest.kt | 3 --- .../BottomSheetMessagePreviewItem.kt | 8 +------ .../vector/app/core/epoxy/util/Extensions.kt | 21 ------------------- .../detail/timeline/item/BindingOptions.kt | 4 +--- .../detail/timeline/item/MessageTextItem.kt | 7 +------ .../reactions/ReactionInfoSimpleItem.kt | 3 +-- .../im/vector/app/features/html/SpanUtils.kt | 10 +-------- 7 files changed, 5 insertions(+), 51 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/core/epoxy/util/Extensions.kt diff --git a/vector/src/androidTest/java/im/vector/app/features/html/SpanUtilsTest.kt b/vector/src/androidTest/java/im/vector/app/features/html/SpanUtilsTest.kt index a42a6f0212..31d8770123 100644 --- a/vector/src/androidTest/java/im/vector/app/features/html/SpanUtilsTest.kt +++ b/vector/src/androidTest/java/im/vector/app/features/html/SpanUtilsTest.kt @@ -108,7 +108,6 @@ class SpanUtilsTest : InstrumentedTest { val string = SpannableString("Text") val result = spanUtils.getBindingOptions(string) result.canUseTextFuture shouldBeEqualTo true - result.preventMutation shouldBeEqualTo false } @Test @@ -117,7 +116,6 @@ class SpanUtilsTest : InstrumentedTest { string.setSpan(StrikethroughSpan(), 10, 23, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) val result = spanUtils.getBindingOptions(string) result.canUseTextFuture shouldBeEqualTo false - result.preventMutation shouldBeEqualTo false } @Test @@ -125,7 +123,6 @@ class SpanUtilsTest : InstrumentedTest { val string = SpannableString("Emoji \uD83D\uDE2E\u200D\uD83D\uDCA8") val result = spanUtils.getBindingOptions(string) result.canUseTextFuture shouldBeEqualTo false - result.preventMutation shouldBeEqualTo true } private fun trueIfAlwaysAllowed() = Build.VERSION.SDK_INT < Build.VERSION_CODES.P diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index f6088b5eda..35db585b79 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -28,14 +28,12 @@ import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick -import im.vector.app.core.epoxy.util.preventMutation import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.item.BindingOptions import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess import im.vector.app.features.media.ImageContentRenderer -import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.util.MatrixItem /** @@ -85,11 +83,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel() { if (bindingOptions?.canUseTextFuture.orFalse()) { holder.messageView.setTextFuture(textFuture) } else { - holder.messageView.text = if (bindingOptions?.preventMutation.orFalse()) { - message?.charSequence.preventMutation() - } else { - message?.charSequence - } + holder.messageView.text = message?.charSequence } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt index e8a2636c82..f6976d96bf 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reactions/ReactionInfoSimpleItem.kt @@ -26,7 +26,6 @@ import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence import im.vector.app.core.epoxy.onClick -import im.vector.app.core.epoxy.util.preventMutation /** * Item displaying an emoji reaction (single line with emoji, author, time) @@ -48,7 +47,7 @@ abstract class ReactionInfoSimpleItem : EpoxyModelWithHolder Date: Mon, 3 Jan 2022 13:49:55 +0100 Subject: [PATCH 4/6] Format --- .../features/home/room/detail/search/SearchResultController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt index 342f1d9562..4c5a52864d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchResultController.kt @@ -101,7 +101,7 @@ class SearchResultController @Inject constructor( // Take new content first @Suppress("UNCHECKED_CAST") -val text = ((event.content?.get("m.new_content") as? Content) ?: event.content)?.get("body") as? String ?: return@forEach + val text = ((event.content?.get("m.new_content") as? Content) ?: event.content)?.get("body") as? String ?: return@forEach val spannable = setHighLightedText(text, data.highlights) ?: return@forEach val eventDate = Calendar.getInstance().apply { From 4642299572430769fa3e53a8ccf9789428b492c4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 Jan 2022 14:29:38 +0100 Subject: [PATCH 5/6] Changelog --- changelog.d/4837.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4837.bugfix diff --git a/changelog.d/4837.bugfix b/changelog.d/4837.bugfix new file mode 100644 index 0000000000..d1eae295f5 --- /dev/null +++ b/changelog.d/4837.bugfix @@ -0,0 +1 @@ +Stop using CharSequence as EpoxyAttribute because it can lead to crash if the CharSequence mutates during rendering. \ No newline at end of file From e03c806fd817e8d3c327ec385a13b61d438f8155 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 3 Jan 2022 15:30:51 +0100 Subject: [PATCH 6/6] Split long line --- .../settings/KeysBackupSettingsRecyclerViewController.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt index f007fe44f0..010255256e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt @@ -199,12 +199,16 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor( val deviceId: String = it.deviceId ?: "" if (!isDeviceKnown) { - description(host.stringProvider.getString(R.string.keys_backup_settings_signature_from_unknown_device, deviceId).toEpoxyCharSequence()) + description(host.stringProvider + .getString(R.string.keys_backup_settings_signature_from_unknown_device, deviceId) + .toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_warning) } else { if (isSignatureValid) { if (host.session.sessionParams.deviceId == it.deviceId) { - description(host.stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_this_device).toEpoxyCharSequence()) + description(host.stringProvider + .getString(R.string.keys_backup_settings_valid_signature_from_this_device) + .toEpoxyCharSequence()) endIconResourceId(R.drawable.e2e_verified) } else { if (isDeviceVerified) {