Merge pull request #3337 from vector-im/dependabot/gradle/epoxy_version-4.6.1
Bump epoxy_version from 4.5.0 to 4.6.1
This commit is contained in:
		
						commit
						57fd580124
					
				@ -290,7 +290,7 @@ android {
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
 | 
			
		||||
    def epoxy_version = '4.5.0'
 | 
			
		||||
    def epoxy_version = '4.6.1'
 | 
			
		||||
    def fragment_version = '1.3.3'
 | 
			
		||||
    def arrow_version = "0.8.2"
 | 
			
		||||
    def markwon_version = '4.1.2'
 | 
			
		||||
 | 
			
		||||
@ -75,4 +75,8 @@
 | 
			
		||||
    <issue id="all">
 | 
			
		||||
        <ignore path="**/generated/resolved/**/resolved.xml" />
 | 
			
		||||
    </issue>
 | 
			
		||||
 | 
			
		||||
    <!-- Bug in lint agp 4.1 incorrectly thinks kotlin forEach is using java 8 API's. -->
 | 
			
		||||
    <!-- FIXME this workaround should be removed in a near future -->
 | 
			
		||||
    <issue id="NewApi" severity="warning" />
 | 
			
		||||
</lint>
 | 
			
		||||
 | 
			
		||||
@ -34,12 +34,13 @@ abstract class BottomSheetGenericController<State : BottomSheetGenericState, Act
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(state: State?) {
 | 
			
		||||
        state ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
        // Title
 | 
			
		||||
        getTitle()?.let { title ->
 | 
			
		||||
            bottomSheetTitleItem {
 | 
			
		||||
                id("title")
 | 
			
		||||
                title(title)
 | 
			
		||||
                subTitle(getSubTitle())
 | 
			
		||||
                subTitle(host.getSubTitle())
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            dividerItem {
 | 
			
		||||
 | 
			
		||||
@ -41,13 +41,14 @@ class AttachmentMiniaturePreviewController @Inject constructor() : TypedEpoxyCon
 | 
			
		||||
    var callback: Callback? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: AttachmentsPreviewViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.attachments.forEachIndexed { index, contentAttachmentData ->
 | 
			
		||||
            attachmentMiniaturePreviewItem {
 | 
			
		||||
                id(contentAttachmentData.queryUri.toString())
 | 
			
		||||
                attachment(contentAttachmentData)
 | 
			
		||||
                checked(data.currentAttachmentIndex == index)
 | 
			
		||||
                clickListener { _ ->
 | 
			
		||||
                    callback?.onAttachmentClicked(index, contentAttachmentData)
 | 
			
		||||
                    host.callback?.onAttachmentClicked(index, contentAttachmentData)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -30,14 +30,15 @@ class AutocompleteCommandController @Inject constructor(private val stringProvid
 | 
			
		||||
        if (data.isNullOrEmpty()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.forEach { command ->
 | 
			
		||||
            autocompleteCommandItem {
 | 
			
		||||
                id(command.command)
 | 
			
		||||
                name(command.command)
 | 
			
		||||
                parameters(command.parameters)
 | 
			
		||||
                description(stringProvider.getString(command.description))
 | 
			
		||||
                description(host.stringProvider.getString(command.description))
 | 
			
		||||
                clickListener { _ ->
 | 
			
		||||
                    listener?.onItemClick(command)
 | 
			
		||||
                    host.listener?.onItemClick(command)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -43,17 +43,18 @@ class AutocompleteEmojiController @Inject constructor(
 | 
			
		||||
        if (data.isNullOrEmpty()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val host = this
 | 
			
		||||
        data
 | 
			
		||||
                .take(MAX)
 | 
			
		||||
                .forEach { emojiItem ->
 | 
			
		||||
                    autocompleteEmojiItem {
 | 
			
		||||
                        id(emojiItem.name)
 | 
			
		||||
                        emojiItem(emojiItem)
 | 
			
		||||
                        emojiTypeFace(emojiTypeface)
 | 
			
		||||
                        emojiTypeFace(host.emojiTypeface)
 | 
			
		||||
                        onClickListener(
 | 
			
		||||
                                object : ReactionClickListener {
 | 
			
		||||
                                    override fun onReactionSelected(reaction: String) {
 | 
			
		||||
                                        listener?.onItemClick(reaction)
 | 
			
		||||
                                        host.listener?.onItemClick(reaction)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                        )
 | 
			
		||||
 | 
			
		||||
@ -34,13 +34,14 @@ class AutocompleteGroupController @Inject constructor() : TypedEpoxyController<L
 | 
			
		||||
        if (data.isNullOrEmpty()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.forEach { groupSummary ->
 | 
			
		||||
            autocompleteMatrixItem {
 | 
			
		||||
                id(groupSummary.groupId)
 | 
			
		||||
                matrixItem(groupSummary.toMatrixItem())
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                clickListener { _ ->
 | 
			
		||||
                    listener?.onItemClick(groupSummary)
 | 
			
		||||
                    host.listener?.onItemClick(groupSummary)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -34,13 +34,14 @@ class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<
 | 
			
		||||
        if (data.isNullOrEmpty()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.forEach { user ->
 | 
			
		||||
            autocompleteMatrixItem {
 | 
			
		||||
                id(user.userId)
 | 
			
		||||
                matrixItem(user.toMatrixItem())
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                clickListener { _ ->
 | 
			
		||||
                    listener?.onItemClick(user)
 | 
			
		||||
                    host.listener?.onItemClick(user)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -32,14 +32,15 @@ class AutocompleteRoomController @Inject constructor(private val avatarRenderer:
 | 
			
		||||
        if (data.isNullOrEmpty()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.forEach { roomSummary ->
 | 
			
		||||
            autocompleteMatrixItem {
 | 
			
		||||
                id(roomSummary.roomId)
 | 
			
		||||
                matrixItem(roomSummary.toMatrixItem())
 | 
			
		||||
                subName(roomSummary.canonicalAlias)
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                clickListener { _ ->
 | 
			
		||||
                    listener?.onItemClick(roomSummary)
 | 
			
		||||
                    host.listener?.onItemClick(roomSummary)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -61,16 +61,18 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderLoading() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        loadingItem {
 | 
			
		||||
            id("loading")
 | 
			
		||||
            loadingText(stringProvider.getString(R.string.loading_contact_book))
 | 
			
		||||
            loadingText(host.stringProvider.getString(R.string.loading_contact_book))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderFailure(failure: Throwable) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        errorWithRetryItem {
 | 
			
		||||
            id("error")
 | 
			
		||||
            text(errorFormatter.toHumanReadable(failure))
 | 
			
		||||
            text(host.errorFormatter.toHumanReadable(failure))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -85,11 +87,12 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderContacts(mappedContacts: List<MappedContact>, onlyBoundContacts: Boolean) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        for (mappedContact in mappedContacts) {
 | 
			
		||||
            contactItem {
 | 
			
		||||
                id(mappedContact.id)
 | 
			
		||||
                mappedContact(mappedContact)
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
            }
 | 
			
		||||
            mappedContact.emails
 | 
			
		||||
                    .forEachIndexed { index, it ->
 | 
			
		||||
@ -101,9 +104,9 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
                            matrixId(it.matrixId)
 | 
			
		||||
                            clickListener {
 | 
			
		||||
                                if (it.matrixId != null) {
 | 
			
		||||
                                    callback?.onMatrixIdClick(it.matrixId)
 | 
			
		||||
                                    host.callback?.onMatrixIdClick(it.matrixId)
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    callback?.onThreePidClick(ThreePid.Email(it.email))
 | 
			
		||||
                                    host.callback?.onThreePidClick(ThreePid.Email(it.email))
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
@ -118,9 +121,9 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
                            matrixId(it.matrixId)
 | 
			
		||||
                            clickListener {
 | 
			
		||||
                                if (it.matrixId != null) {
 | 
			
		||||
                                    callback?.onMatrixIdClick(it.matrixId)
 | 
			
		||||
                                    host.callback?.onMatrixIdClick(it.matrixId)
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    callback?.onThreePidClick(ThreePid.Msisdn(it.phoneNumber))
 | 
			
		||||
                                    host.callback?.onThreePidClick(ThreePid.Msisdn(it.phoneNumber))
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
@ -129,6 +132,7 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderEmptyState(hasSearch: Boolean) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val noResultRes = if (hasSearch) {
 | 
			
		||||
            R.string.no_result_placeholder
 | 
			
		||||
        } else {
 | 
			
		||||
@ -136,7 +140,7 @@ class ContactsBookController @Inject constructor(
 | 
			
		||||
        }
 | 
			
		||||
        noResultItem {
 | 
			
		||||
            id("noResult")
 | 
			
		||||
            text(stringProvider.getString(noResultRes))
 | 
			
		||||
            text(host.stringProvider.getString(noResultRes))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,9 +35,11 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersion
 | 
			
		||||
import java.util.UUID
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class KeysBackupSettingsRecyclerViewController @Inject constructor(private val stringProvider: StringProvider,
 | 
			
		||||
                                                                   private val vectorPreferences: VectorPreferences,
 | 
			
		||||
                                                                   private val session: Session) : TypedEpoxyController<KeysBackupSettingViewState>() {
 | 
			
		||||
class KeysBackupSettingsRecyclerViewController @Inject constructor(
 | 
			
		||||
        private val stringProvider: StringProvider,
 | 
			
		||||
        private val vectorPreferences: VectorPreferences,
 | 
			
		||||
        private val session: Session
 | 
			
		||||
) : TypedEpoxyController<KeysBackupSettingViewState>() {
 | 
			
		||||
 | 
			
		||||
    var listener: Listener? = null
 | 
			
		||||
 | 
			
		||||
@ -46,6 +48,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val host = this
 | 
			
		||||
        var isBackupAlreadySetup = false
 | 
			
		||||
 | 
			
		||||
        val keyBackupState = data.keysBackupState
 | 
			
		||||
@ -55,8 +58,8 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            KeysBackupState.Unknown                    -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    text(stringProvider.getString(R.string.keys_backup_unable_to_get_keys_backup_data))
 | 
			
		||||
                    listener { listener?.loadKeysBackupState() }
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.keys_backup_unable_to_get_keys_backup_data))
 | 
			
		||||
                    listener { host.listener?.loadKeysBackupState() }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Nothing else to display
 | 
			
		||||
@ -65,17 +68,17 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            KeysBackupState.CheckingBackUpOnHomeserver -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.keys_backup_settings_checking_backup_state))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.keys_backup_settings_checking_backup_state))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            KeysBackupState.Disabled                   -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    title(stringProvider.getString(R.string.keys_backup_settings_status_not_setup))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.keys_backup_settings_status_not_setup))
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
 | 
			
		||||
                    if (data.keysBackupVersionTrust()?.usable == false) {
 | 
			
		||||
                        description(stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -86,10 +89,10 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            KeysBackupState.Enabling                   -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    title(stringProvider.getString(R.string.keys_backup_settings_status_ko))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.keys_backup_settings_status_ko))
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    if (data.keysBackupVersionTrust()?.usable == false) {
 | 
			
		||||
                        description(stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        description(keyBackupState.toString())
 | 
			
		||||
                    }
 | 
			
		||||
@ -101,12 +104,12 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            KeysBackupState.ReadyToBackUp              -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    title(stringProvider.getString(R.string.keys_backup_settings_status_ok))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok))
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    if (data.keysBackupVersionTrust()?.usable == false) {
 | 
			
		||||
                        description(stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        description(stringProvider.getString(R.string.keys_backup_info_keys_all_backup_up))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.keys_backup_info_keys_all_backup_up))
 | 
			
		||||
                    }
 | 
			
		||||
                    endIconResourceId(R.drawable.unit_test_ok)
 | 
			
		||||
                }
 | 
			
		||||
@ -117,19 +120,20 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            KeysBackupState.BackingUp                  -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("summary")
 | 
			
		||||
                    title(stringProvider.getString(R.string.keys_backup_settings_status_ok))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.keys_backup_settings_status_ok))
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    hasIndeterminateProcess(true)
 | 
			
		||||
 | 
			
		||||
                    val totalKeys = session.cryptoService().inboundGroupSessionsCount(false)
 | 
			
		||||
                    val backedUpKeys = session.cryptoService().inboundGroupSessionsCount(true)
 | 
			
		||||
                    val totalKeys = host.session.cryptoService().inboundGroupSessionsCount(false)
 | 
			
		||||
                    val backedUpKeys = host.session.cryptoService().inboundGroupSessionsCount(true)
 | 
			
		||||
 | 
			
		||||
                    val remainingKeysToBackup = totalKeys - backedUpKeys
 | 
			
		||||
 | 
			
		||||
                    if (data.keysBackupVersionTrust()?.usable == false) {
 | 
			
		||||
                        description(stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        description(stringProvider.getQuantityString(R.plurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup))
 | 
			
		||||
                        description(host.stringProvider
 | 
			
		||||
                                .getQuantityString(R.plurals.keys_backup_info_keys_backing_up, remainingKeysToBackup, remainingKeysToBackup))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -141,13 +145,13 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            // Add infos
 | 
			
		||||
            genericItem {
 | 
			
		||||
                id("version")
 | 
			
		||||
                title(stringProvider.getString(R.string.keys_backup_info_title_version))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.keys_backup_info_title_version))
 | 
			
		||||
                description(keyVersionResult?.version ?: "")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            genericItem {
 | 
			
		||||
                id("algorithm")
 | 
			
		||||
                title(stringProvider.getString(R.string.keys_backup_info_title_algorithm))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.keys_backup_info_title_algorithm))
 | 
			
		||||
                description(keyVersionResult?.algorithm ?: "")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -161,19 +165,20 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            id("footer")
 | 
			
		||||
 | 
			
		||||
            if (isBackupAlreadySetup) {
 | 
			
		||||
                textButton1(stringProvider.getString(R.string.keys_backup_settings_restore_backup_button))
 | 
			
		||||
                clickOnButton1(View.OnClickListener { listener?.didSelectRestoreMessageRecovery() })
 | 
			
		||||
                textButton1(host.stringProvider.getString(R.string.keys_backup_settings_restore_backup_button))
 | 
			
		||||
                clickOnButton1(View.OnClickListener { host.listener?.didSelectRestoreMessageRecovery() })
 | 
			
		||||
 | 
			
		||||
                textButton2(stringProvider.getString(R.string.keys_backup_settings_delete_backup_button))
 | 
			
		||||
                clickOnButton2(View.OnClickListener { listener?.didSelectDeleteSetupMessageRecovery() })
 | 
			
		||||
                textButton2(host.stringProvider.getString(R.string.keys_backup_settings_delete_backup_button))
 | 
			
		||||
                clickOnButton2(View.OnClickListener { host.listener?.didSelectDeleteSetupMessageRecovery() })
 | 
			
		||||
            } else {
 | 
			
		||||
                textButton1(stringProvider.getString(R.string.keys_backup_setup))
 | 
			
		||||
                clickOnButton1(View.OnClickListener { listener?.didSelectSetupMessageRecovery() })
 | 
			
		||||
                textButton1(host.stringProvider.getString(R.string.keys_backup_setup))
 | 
			
		||||
                clickOnButton1(View.OnClickListener { host.listener?.didSelectSetupMessageRecovery() })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildKeysBackupTrust(keysVersionTrust: Async<KeysBackupVersionTrust>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (keysVersionTrust) {
 | 
			
		||||
            is Uninitialized -> Unit
 | 
			
		||||
            is Loading       -> {
 | 
			
		||||
@ -185,7 +190,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
                keysVersionTrust().signatures.forEach {
 | 
			
		||||
                    genericItem {
 | 
			
		||||
                        id(UUID.randomUUID().toString())
 | 
			
		||||
                        title(stringProvider.getString(R.string.keys_backup_info_title_signature))
 | 
			
		||||
                        title(host.stringProvider.getString(R.string.keys_backup_info_title_signature))
 | 
			
		||||
 | 
			
		||||
                        val isDeviceKnown = it.device != null
 | 
			
		||||
                        val isDeviceVerified = it.device?.isVerified ?: false
 | 
			
		||||
@ -193,19 +198,21 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
                        val deviceId: String = it.deviceId ?: ""
 | 
			
		||||
 | 
			
		||||
                        if (!isDeviceKnown) {
 | 
			
		||||
                            description(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))
 | 
			
		||||
                            endIconResourceId(R.drawable.e2e_warning)
 | 
			
		||||
                        } else {
 | 
			
		||||
                            if (isSignatureValid) {
 | 
			
		||||
                                if (session.sessionParams.deviceId == it.deviceId) {
 | 
			
		||||
                                    description(stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_this_device))
 | 
			
		||||
                                if (host.session.sessionParams.deviceId == it.deviceId) {
 | 
			
		||||
                                    description(host.stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_this_device))
 | 
			
		||||
                                    endIconResourceId(R.drawable.e2e_verified)
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    if (isDeviceVerified) {
 | 
			
		||||
                                        description(stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_verified_device, deviceId))
 | 
			
		||||
                                        description(host.stringProvider
 | 
			
		||||
                                                .getString(R.string.keys_backup_settings_valid_signature_from_verified_device, deviceId))
 | 
			
		||||
                                        endIconResourceId(R.drawable.e2e_verified)
 | 
			
		||||
                                    } else {
 | 
			
		||||
                                        description(stringProvider.getString(R.string.keys_backup_settings_valid_signature_from_unverified_device, deviceId))
 | 
			
		||||
                                        description(host.stringProvider
 | 
			
		||||
                                                .getString(R.string.keys_backup_settings_valid_signature_from_unverified_device, deviceId))
 | 
			
		||||
                                        endIconResourceId(R.drawable.e2e_warning)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
@ -213,9 +220,11 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
                                // Invalid signature
 | 
			
		||||
                                endIconResourceId(R.drawable.e2e_warning)
 | 
			
		||||
                                if (isDeviceVerified) {
 | 
			
		||||
                                    description(stringProvider.getString(R.string.keys_backup_settings_invalid_signature_from_verified_device, deviceId))
 | 
			
		||||
                                    description(host.stringProvider
 | 
			
		||||
                                            .getString(R.string.keys_backup_settings_invalid_signature_from_verified_device, deviceId))
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    description(stringProvider.getString(R.string.keys_backup_settings_invalid_signature_from_unverified_device, deviceId))
 | 
			
		||||
                                    description(host.stringProvider
 | 
			
		||||
                                            .getString(R.string.keys_backup_settings_invalid_signature_from_unverified_device, deviceId))
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
@ -225,8 +234,8 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(private val s
 | 
			
		||||
            is Fail          -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("trust")
 | 
			
		||||
                    text(stringProvider.getString(R.string.keys_backup_unable_to_get_trust_info))
 | 
			
		||||
                    listener { listener?.loadTrustData() }
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.keys_backup_unable_to_get_trust_info))
 | 
			
		||||
                    listener { host.listener?.loadTrustData() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -44,17 +44,17 @@ class VerificationCancelController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val state = viewState ?: return
 | 
			
		||||
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (state.isMe) {
 | 
			
		||||
            if (state.currentDeviceCanCrossSign) {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_trusted))
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verify_cancel_self_verification_from_untrusted))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -63,9 +63,9 @@ class VerificationCancelController @Inject constructor(
 | 
			
		||||
            bottomSheetVerificationNoticeItem {
 | 
			
		||||
                id("notice")
 | 
			
		||||
                notice(
 | 
			
		||||
                        stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID)
 | 
			
		||||
                        host.stringProvider.getString(R.string.verify_cancel_other, otherDisplayName, otherUserID)
 | 
			
		||||
                                .toSpannable()
 | 
			
		||||
                                .colorizeMatchingText(otherUserID, colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color))
 | 
			
		||||
                                .colorizeMatchingText(otherUserID, host.colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color))
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -76,11 +76,11 @@ class VerificationCancelController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("cancel")
 | 
			
		||||
            title(stringProvider.getString(R.string.skip))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.skip))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
            listener { listener?.onTapCancel() }
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
            listener { host.listener?.onTapCancel() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dividerItem {
 | 
			
		||||
@ -89,11 +89,11 @@ class VerificationCancelController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("continue")
 | 
			
		||||
            title(stringProvider.getString(R.string._continue))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string._continue))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            listener { listener?.onTapContinue() }
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            listener { host.listener?.onTapContinue() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -43,9 +43,10 @@ class VerificationNotMeController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        bottomSheetVerificationNoticeItem {
 | 
			
		||||
            id("notice")
 | 
			
		||||
            notice(eventHtmlRenderer.render(stringProvider.getString(R.string.verify_not_me_self_verification)))
 | 
			
		||||
            notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dividerItem {
 | 
			
		||||
@ -54,11 +55,11 @@ class VerificationNotMeController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("skip")
 | 
			
		||||
            title(stringProvider.getString(R.string.skip))
 | 
			
		||||
            titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.skip))
 | 
			
		||||
            titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            listener { listener?.onTapSkip() }
 | 
			
		||||
            iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            listener { host.listener?.onTapSkip() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dividerItem {
 | 
			
		||||
@ -67,11 +68,11 @@ class VerificationNotMeController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("settings")
 | 
			
		||||
            title(stringProvider.getString(R.string.settings))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.settings))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            listener { listener?.onTapSettings() }
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent))
 | 
			
		||||
            listener { host.listener?.onTapSettings() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,11 +42,12 @@ class VerificationChooseMethodController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val state = viewState ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (state.otherCanScanQrCode || state.otherCanShowQrCode) {
 | 
			
		||||
            bottomSheetVerificationNoticeItem {
 | 
			
		||||
                id("notice")
 | 
			
		||||
                notice(stringProvider.getString(R.string.verification_scan_notice))
 | 
			
		||||
                notice(host.stringProvider.getString(R.string.verification_scan_notice))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (state.otherCanScanQrCode && !state.qrCodeText.isNullOrBlank()) {
 | 
			
		||||
@ -63,11 +64,11 @@ class VerificationChooseMethodController @Inject constructor(
 | 
			
		||||
            if (state.otherCanShowQrCode) {
 | 
			
		||||
                bottomSheetVerificationActionItem {
 | 
			
		||||
                    id("openCamera")
 | 
			
		||||
                    title(stringProvider.getString(R.string.verification_scan_their_code))
 | 
			
		||||
                    titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.verification_scan_their_code))
 | 
			
		||||
                    titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    iconRes(R.drawable.ic_camera)
 | 
			
		||||
                    iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    listener { listener?.openCamera() }
 | 
			
		||||
                    iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    listener { host.listener?.openCamera() }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                dividerItem {
 | 
			
		||||
@ -77,21 +78,21 @@ class VerificationChooseMethodController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("openEmoji")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_scan_emoji_title))
 | 
			
		||||
                titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                subTitle(stringProvider.getString(R.string.verification_scan_emoji_subtitle))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_scan_emoji_title))
 | 
			
		||||
                titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                subTitle(host.stringProvider.getString(R.string.verification_scan_emoji_subtitle))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { listener?.doVerifyBySas() }
 | 
			
		||||
                iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { host.listener?.doVerifyBySas() }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state.sasModeAvailable) {
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("openEmoji")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_no_scan_emoji_title))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { listener?.doVerifyBySas() }
 | 
			
		||||
                iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { host.listener?.doVerifyBySas() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -102,12 +103,12 @@ class VerificationChooseMethodController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("wasnote")
 | 
			
		||||
                title(stringProvider.getString(R.string.verify_new_session_was_not_me))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                subTitle(stringProvider.getString(R.string.verify_new_session_compromized))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verify_new_session_was_not_me))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { listener?.onClickOnWasNotMe() }
 | 
			
		||||
                iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { host.listener?.onClickOnWasNotMe() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -45,12 +45,13 @@ class VerificationConclusionController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val state = viewState ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        when (state.conclusionState) {
 | 
			
		||||
            ConclusionState.SUCCESS   -> {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(
 | 
			
		||||
                    notice(host.stringProvider.getString(
 | 
			
		||||
                            if (state.isSelfVerification) R.string.verification_conclusion_ok_self_notice
 | 
			
		||||
                            else R.string.verification_conclusion_ok_notice))
 | 
			
		||||
                }
 | 
			
		||||
@ -65,7 +66,7 @@ class VerificationConclusionController @Inject constructor(
 | 
			
		||||
            ConclusionState.WARNING   -> {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verification_conclusion_not_secure))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verification_conclusion_not_secure))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationBigImageItem {
 | 
			
		||||
@ -75,7 +76,7 @@ class VerificationConclusionController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("warning_notice")
 | 
			
		||||
                    notice(eventHtmlRenderer.render(stringProvider.getString(R.string.verification_conclusion_compromised)))
 | 
			
		||||
                    notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verification_conclusion_compromised)))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomDone()
 | 
			
		||||
@ -83,7 +84,7 @@ class VerificationConclusionController @Inject constructor(
 | 
			
		||||
            ConclusionState.CANCELLED -> {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice_cancelled")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verify_cancelled_notice))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verify_cancelled_notice))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                dividerItem {
 | 
			
		||||
@ -92,28 +93,29 @@ class VerificationConclusionController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationActionItem {
 | 
			
		||||
                    id("got_it")
 | 
			
		||||
                    title(stringProvider.getString(R.string.sas_got_it))
 | 
			
		||||
                    titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.sas_got_it))
 | 
			
		||||
                    titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                    iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    listener { listener?.onButtonTapped() }
 | 
			
		||||
                    iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    listener { host.listener?.onButtonTapped() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun bottomDone() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        dividerItem {
 | 
			
		||||
            id("sep0")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("done")
 | 
			
		||||
            title(stringProvider.getString(R.string.done))
 | 
			
		||||
            titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.done))
 | 
			
		||||
            titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            listener { listener?.onButtonTapped() }
 | 
			
		||||
            iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            listener { host.listener?.onButtonTapped() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -58,11 +58,12 @@ class VerificationEmojiCodeController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildEmojiItem(state: VerificationEmojiCodeViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (val emojiDescription = state.emojiDescription) {
 | 
			
		||||
            is Success -> {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verification_emoji_notice))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verification_emoji_notice))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationEmojisItem {
 | 
			
		||||
@ -81,24 +82,25 @@ class VerificationEmojiCodeController @Inject constructor(
 | 
			
		||||
            is Fail    -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(emojiDescription.error))
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(emojiDescription.error))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else       -> {
 | 
			
		||||
                bottomSheetVerificationWaitingItem {
 | 
			
		||||
                    id("waiting")
 | 
			
		||||
                    title(stringProvider.getString(R.string.please_wait))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.please_wait))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildDecimal(state: VerificationEmojiCodeViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (val decimalDescription = state.decimalDescription) {
 | 
			
		||||
            is Success -> {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verification_code_notice))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verification_code_notice))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationDecimalCodeItem {
 | 
			
		||||
@ -111,19 +113,20 @@ class VerificationEmojiCodeController @Inject constructor(
 | 
			
		||||
            is Fail    -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(decimalDescription.error))
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(decimalDescription.error))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else       -> {
 | 
			
		||||
                bottomSheetVerificationWaitingItem {
 | 
			
		||||
                    id("waiting")
 | 
			
		||||
                    title(stringProvider.getString(R.string.please_wait))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.please_wait))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildActions(state: VerificationEmojiCodeViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        dividerItem {
 | 
			
		||||
            id("sep0")
 | 
			
		||||
        }
 | 
			
		||||
@ -131,27 +134,27 @@ class VerificationEmojiCodeController @Inject constructor(
 | 
			
		||||
        if (state.isWaitingFromOther) {
 | 
			
		||||
            bottomSheetVerificationWaitingItem {
 | 
			
		||||
                id("waiting")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_request_waiting_for, state.otherUser?.getBestName() ?: ""))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_request_waiting_for, state.otherUser?.getBestName() ?: ""))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("ko")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_sas_do_not_match))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_sas_do_not_match))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
                iconRes(R.drawable.ic_check_off)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
                listener { listener?.onDoNotMatchButtonTapped() }
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
                listener { host.listener?.onDoNotMatchButtonTapped() }
 | 
			
		||||
            }
 | 
			
		||||
            dividerItem {
 | 
			
		||||
                id("sep1")
 | 
			
		||||
            }
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("ok")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_sas_match))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_sas_match))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_check_on)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                listener { listener?.onMatchButtonTapped() }
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                listener { host.listener?.onMatchButtonTapped() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -40,11 +40,12 @@ class VerificationQRWaitingController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val params = args ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationNoticeItem {
 | 
			
		||||
            id("notice")
 | 
			
		||||
            apply {
 | 
			
		||||
                notice(stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice))
 | 
			
		||||
                notice(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting_notice))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -55,7 +56,7 @@ class VerificationQRWaitingController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationWaitingItem {
 | 
			
		||||
            id("waiting")
 | 
			
		||||
            title(stringProvider.getString(R.string.qr_code_scanned_verif_waiting, params.otherUserName))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.qr_code_scanned_verif_waiting, params.otherUserName))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -44,15 +44,16 @@ class VerificationQrScannedByOtherController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val state = viewState ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationNoticeItem {
 | 
			
		||||
            id("notice")
 | 
			
		||||
            apply {
 | 
			
		||||
                if (state.isMe) {
 | 
			
		||||
                    notice(stringProvider.getString(R.string.qr_code_scanned_self_verif_notice))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.qr_code_scanned_self_verif_notice))
 | 
			
		||||
                } else {
 | 
			
		||||
                    val name = state.otherUserMxItem?.getBestName() ?: ""
 | 
			
		||||
                    notice(stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.qr_code_scanned_by_other_notice, name))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -68,11 +69,11 @@ class VerificationQrScannedByOtherController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("deny")
 | 
			
		||||
            title(stringProvider.getString(R.string.qr_code_scanned_by_other_no))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_no))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
            iconRes(R.drawable.ic_check_off)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
            listener { listener?.onUserDeniesQrCodeScanned() }
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.vector_error_color))
 | 
			
		||||
            listener { host.listener?.onUserDeniesQrCodeScanned() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dividerItem {
 | 
			
		||||
@ -81,11 +82,11 @@ class VerificationQrScannedByOtherController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("confirm")
 | 
			
		||||
            title(stringProvider.getString(R.string.qr_code_scanned_by_other_yes))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.qr_code_scanned_by_other_yes))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_check_on)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            listener { listener?.onUserConfirmsQrCodeScanned() }
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            listener { host.listener?.onUserConfirmsQrCodeScanned() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -50,12 +50,13 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val state = viewState ?: return
 | 
			
		||||
        val matrixItem = viewState?.otherUserMxItem ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (state.selfVerificationMode) {
 | 
			
		||||
            if (state.hasAnyOtherSession) {
 | 
			
		||||
                bottomSheetVerificationNoticeItem {
 | 
			
		||||
                    id("notice")
 | 
			
		||||
                    notice(stringProvider.getString(R.string.verification_open_other_to_verify))
 | 
			
		||||
                    notice(host.stringProvider.getString(R.string.verification_open_other_to_verify))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomSheetSelfWaitItem {
 | 
			
		||||
@ -75,12 +76,12 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
                }
 | 
			
		||||
                bottomSheetVerificationActionItem {
 | 
			
		||||
                    id("passphrase")
 | 
			
		||||
                    title(stringProvider.getString(R.string.verification_cannot_access_other_session))
 | 
			
		||||
                    titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.verification_cannot_access_other_session))
 | 
			
		||||
                    titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    subTitle(subtitle)
 | 
			
		||||
                    iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                    iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    listener { listener?.onClickRecoverFromPassphrase() }
 | 
			
		||||
                    iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    listener { host.listener?.onClickRecoverFromPassphrase() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -90,11 +91,11 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("skip")
 | 
			
		||||
                title(stringProvider.getString(R.string.skip))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.skip))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                listener { listener?.onClickSkip() }
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                listener { host.listener?.onClickSkip() }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            val styledText =
 | 
			
		||||
@ -121,18 +122,18 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
                is Uninitialized -> {
 | 
			
		||||
                    bottomSheetVerificationActionItem {
 | 
			
		||||
                        id("start")
 | 
			
		||||
                        title(stringProvider.getString(R.string.start_verification))
 | 
			
		||||
                        titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                        subTitle(stringProvider.getString(R.string.verification_request_start_notice))
 | 
			
		||||
                        title(host.stringProvider.getString(R.string.start_verification))
 | 
			
		||||
                        titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                        subTitle(host.stringProvider.getString(R.string.verification_request_start_notice))
 | 
			
		||||
                        iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                        iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                        listener { listener?.onClickOnVerificationStart() }
 | 
			
		||||
                        iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                        listener { host.listener?.onClickOnVerificationStart() }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                is Loading       -> {
 | 
			
		||||
                    bottomSheetVerificationWaitingItem {
 | 
			
		||||
                        id("waiting")
 | 
			
		||||
                        title(stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName()))
 | 
			
		||||
                        title(host.stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName()))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                is Success       -> {
 | 
			
		||||
@ -140,12 +141,12 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
                        if (state.isMe) {
 | 
			
		||||
                            bottomSheetVerificationWaitingItem {
 | 
			
		||||
                                id("waiting")
 | 
			
		||||
                                title(stringProvider.getString(R.string.verification_request_waiting))
 | 
			
		||||
                                title(host.stringProvider.getString(R.string.verification_request_waiting))
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            bottomSheetVerificationWaitingItem {
 | 
			
		||||
                                id("waiting")
 | 
			
		||||
                                title(stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName()))
 | 
			
		||||
                                title(host.stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName()))
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -160,12 +161,12 @@ class VerificationRequestController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("wasnote")
 | 
			
		||||
                title(stringProvider.getString(R.string.verify_new_session_was_not_me))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                subTitle(stringProvider.getString(R.string.verify_new_session_compromized))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verify_new_session_was_not_me))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { listener?.onClickOnWasNotMe() }
 | 
			
		||||
                iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                listener { host.listener?.onClickOnWasNotMe() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -34,25 +34,26 @@ class RoomDevToolRootController @Inject constructor(
 | 
			
		||||
    var interactionListener: DevToolsInteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        genericButtonItem {
 | 
			
		||||
            id("explore")
 | 
			
		||||
            text(stringProvider.getString(R.string.dev_tools_explore_room_state))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.dev_tools_explore_room_state))
 | 
			
		||||
            buttonClickAction(View.OnClickListener {
 | 
			
		||||
                interactionListener?.processAction(RoomDevToolAction.ExploreRoomState)
 | 
			
		||||
                host.interactionListener?.processAction(RoomDevToolAction.ExploreRoomState)
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        genericButtonItem {
 | 
			
		||||
            id("send")
 | 
			
		||||
            text(stringProvider.getString(R.string.dev_tools_send_custom_event))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.dev_tools_send_custom_event))
 | 
			
		||||
            buttonClickAction(View.OnClickListener {
 | 
			
		||||
                interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(false))
 | 
			
		||||
                host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(false))
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        genericButtonItem {
 | 
			
		||||
            id("send_state")
 | 
			
		||||
            text(stringProvider.getString(R.string.dev_tools_send_state_event))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.dev_tools_send_state_event))
 | 
			
		||||
            buttonClickAction(View.OnClickListener {
 | 
			
		||||
                interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(true))
 | 
			
		||||
                host.interactionListener?.processAction(RoomDevToolAction.SendCustomEvent(true))
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -32,6 +32,7 @@ class RoomDevToolSendFormController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomDevToolViewState?) {
 | 
			
		||||
        val sendEventForm = (data?.displayMode as? RoomDevToolViewState.Mode.SendEventForm) ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("topSpace")
 | 
			
		||||
@ -41,10 +42,10 @@ class RoomDevToolSendFormController @Inject constructor(
 | 
			
		||||
            id("event_type")
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(data.sendEventDraft?.type)
 | 
			
		||||
            hint(stringProvider.getString(R.string.dev_tools_form_hint_type))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.dev_tools_form_hint_type))
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                interactionListener?.processAction(RoomDevToolAction.CustomEventTypeChange(text))
 | 
			
		||||
                host.interactionListener?.processAction(RoomDevToolAction.CustomEventTypeChange(text))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -53,10 +54,10 @@ class RoomDevToolSendFormController @Inject constructor(
 | 
			
		||||
                id("state_key")
 | 
			
		||||
                enabled(true)
 | 
			
		||||
                value(data.sendEventDraft?.stateKey)
 | 
			
		||||
                hint(stringProvider.getString(R.string.dev_tools_form_hint_state_key))
 | 
			
		||||
                hint(host.stringProvider.getString(R.string.dev_tools_form_hint_state_key))
 | 
			
		||||
                showBottomSeparator(false)
 | 
			
		||||
                onTextChange { text ->
 | 
			
		||||
                    interactionListener?.processAction(RoomDevToolAction.CustomEventStateKeyChange(text))
 | 
			
		||||
                    host.interactionListener?.processAction(RoomDevToolAction.CustomEventStateKeyChange(text))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -65,10 +66,10 @@ class RoomDevToolSendFormController @Inject constructor(
 | 
			
		||||
            id("event_content")
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(data.sendEventDraft?.content)
 | 
			
		||||
            hint(stringProvider.getString(R.string.dev_tools_form_hint_event_content))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.dev_tools_form_hint_event_content))
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                interactionListener?.processAction(RoomDevToolAction.CustomEventContentChange(text))
 | 
			
		||||
                host.interactionListener?.processAction(RoomDevToolAction.CustomEventContentChange(text))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ class RoomStateListController @Inject constructor(
 | 
			
		||||
    var interactionListener: DevToolsInteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomDevToolViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data?.displayMode) {
 | 
			
		||||
            RoomDevToolViewState.Mode.StateEventList -> {
 | 
			
		||||
                val stateEventsGroups = data.stateEvents.invoke().orEmpty().groupBy { it.getClearType() }
 | 
			
		||||
@ -42,17 +43,17 @@ class RoomStateListController @Inject constructor(
 | 
			
		||||
                if (stateEventsGroups.isEmpty()) {
 | 
			
		||||
                    noResultItem {
 | 
			
		||||
                        id("no state events")
 | 
			
		||||
                        text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    stateEventsGroups.forEach { entry ->
 | 
			
		||||
                        genericItem {
 | 
			
		||||
                            id(entry.key)
 | 
			
		||||
                            title(entry.key)
 | 
			
		||||
                            description(stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size))
 | 
			
		||||
                            description(host.stringProvider.getQuantityString(R.plurals.entries, entry.value.size, entry.value.size))
 | 
			
		||||
                            itemClickAction(GenericItem.Action("view").apply {
 | 
			
		||||
                                perform = Runnable {
 | 
			
		||||
                                    interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key))
 | 
			
		||||
                                    host.interactionListener?.processAction(RoomDevToolAction.ShowStateEventType(entry.key))
 | 
			
		||||
                                }
 | 
			
		||||
                            })
 | 
			
		||||
                        }
 | 
			
		||||
@ -64,7 +65,7 @@ class RoomStateListController @Inject constructor(
 | 
			
		||||
                if (stateEvents.isEmpty()) {
 | 
			
		||||
                    noResultItem {
 | 
			
		||||
                        id("no state events")
 | 
			
		||||
                        text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    stateEvents.forEach { stateEvent ->
 | 
			
		||||
@ -80,13 +81,13 @@ class RoomStateListController @Inject constructor(
 | 
			
		||||
                            title(span {
 | 
			
		||||
                                +"Type: "
 | 
			
		||||
                                span {
 | 
			
		||||
                                    textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                    textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                    text = "\"${stateEvent.type}\""
 | 
			
		||||
                                    textStyle = "normal"
 | 
			
		||||
                                }
 | 
			
		||||
                                +"\nState Key: "
 | 
			
		||||
                                span {
 | 
			
		||||
                                    textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                    textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                    text = stateEvent.stateKey.let { "\"$it\"" }
 | 
			
		||||
                                    textStyle = "normal"
 | 
			
		||||
                                }
 | 
			
		||||
@ -94,7 +95,7 @@ class RoomStateListController @Inject constructor(
 | 
			
		||||
                            description(contentJson)
 | 
			
		||||
                            itemClickAction(GenericItem.Action("view").apply {
 | 
			
		||||
                                perform = Runnable {
 | 
			
		||||
                                    interactionListener?.processAction(RoomDevToolAction.ShowStateEvent(stateEvent))
 | 
			
		||||
                                    host.interactionListener?.processAction(RoomDevToolAction.ShowStateEvent(stateEvent))
 | 
			
		||||
                                }
 | 
			
		||||
                            })
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -74,6 +74,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildConsentSection(data: DiscoverySettingsState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("idConsentTitle")
 | 
			
		||||
            titleResId(R.string.settings_discovery_consent_title)
 | 
			
		||||
@ -86,10 +87,10 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            settingsButtonItem {
 | 
			
		||||
                id("idConsentButton")
 | 
			
		||||
                colorProvider(colorProvider)
 | 
			
		||||
                colorProvider(host.colorProvider)
 | 
			
		||||
                buttonTitleId(R.string.settings_discovery_consent_action_revoke)
 | 
			
		||||
                buttonStyle(ButtonStyle.DESTRUCTIVE)
 | 
			
		||||
                buttonClickListener { listener?.onTapUpdateUserConsent(false) }
 | 
			
		||||
                buttonClickListener { host.listener?.onTapUpdateUserConsent(false) }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            settingsInfoItem {
 | 
			
		||||
@ -98,15 +99,16 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            settingsButtonItem {
 | 
			
		||||
                id("idConsentButton")
 | 
			
		||||
                colorProvider(colorProvider)
 | 
			
		||||
                colorProvider(host.colorProvider)
 | 
			
		||||
                buttonTitleId(R.string.settings_discovery_consent_action_give_consent)
 | 
			
		||||
                buttonClickListener { listener?.onTapUpdateUserConsent(true) }
 | 
			
		||||
                buttonClickListener { host.listener?.onTapUpdateUserConsent(true) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildIdentityServerSection(data: DiscoverySettingsState) {
 | 
			
		||||
        val identityServer = data.identityServer() ?: stringProvider.getString(R.string.none)
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("idServerTitle")
 | 
			
		||||
@ -121,22 +123,22 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
        if (data.identityServer() != null && data.termsNotSigned) {
 | 
			
		||||
            settingsInfoItem {
 | 
			
		||||
                id("idServerFooter")
 | 
			
		||||
                helperText(stringProvider.getString(R.string.settings_agree_to_terms, identityServer))
 | 
			
		||||
                helperText(host.stringProvider.getString(R.string.settings_agree_to_terms, identityServer))
 | 
			
		||||
                showCompoundDrawable(true)
 | 
			
		||||
                itemClickListener(View.OnClickListener { listener?.openIdentityServerTerms() })
 | 
			
		||||
                itemClickListener(View.OnClickListener { host.listener?.openIdentityServerTerms() })
 | 
			
		||||
            }
 | 
			
		||||
            settingsButtonItem {
 | 
			
		||||
                id("seeTerms")
 | 
			
		||||
                colorProvider(colorProvider)
 | 
			
		||||
                buttonTitle(stringProvider.getString(R.string.open_terms_of, identityServer))
 | 
			
		||||
                buttonClickListener { listener?.openIdentityServerTerms() }
 | 
			
		||||
                colorProvider(host.colorProvider)
 | 
			
		||||
                buttonTitle(host.stringProvider.getString(R.string.open_terms_of, identityServer))
 | 
			
		||||
                buttonClickListener { host.listener?.openIdentityServerTerms() }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            settingsInfoItem {
 | 
			
		||||
                id("idServerFooter")
 | 
			
		||||
                showCompoundDrawable(false)
 | 
			
		||||
                if (data.identityServer() != null) {
 | 
			
		||||
                    helperText(stringProvider.getString(R.string.settings_discovery_identity_server_info, identityServer))
 | 
			
		||||
                    helperText(host.stringProvider.getString(R.string.settings_discovery_identity_server_info, identityServer))
 | 
			
		||||
                } else {
 | 
			
		||||
                    helperTextResId(R.string.settings_discovery_identity_server_info_none)
 | 
			
		||||
                }
 | 
			
		||||
@ -145,13 +147,13 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        settingsButtonItem {
 | 
			
		||||
            id("change")
 | 
			
		||||
            colorProvider(colorProvider)
 | 
			
		||||
            colorProvider(host.colorProvider)
 | 
			
		||||
            if (data.identityServer() == null) {
 | 
			
		||||
                buttonTitleId(R.string.add_identity_server)
 | 
			
		||||
            } else {
 | 
			
		||||
                buttonTitleId(R.string.change_identity_server)
 | 
			
		||||
            }
 | 
			
		||||
            buttonClickListener { listener?.onTapChangeIdentityServer() }
 | 
			
		||||
            buttonClickListener { host.listener?.onTapChangeIdentityServer() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (data.identityServer() != null) {
 | 
			
		||||
@ -161,15 +163,16 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            settingsButtonItem {
 | 
			
		||||
                id("remove")
 | 
			
		||||
                colorProvider(colorProvider)
 | 
			
		||||
                colorProvider(host.colorProvider)
 | 
			
		||||
                buttonTitleId(R.string.disconnect_identity_server)
 | 
			
		||||
                buttonStyle(ButtonStyle.DESTRUCTIVE)
 | 
			
		||||
                buttonClickListener { listener?.onTapDisconnectIdentityServer() }
 | 
			
		||||
                buttonClickListener { host.listener?.onTapDisconnectIdentityServer() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildEmailsSection(emails: Async<List<PidInfo>>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("emails")
 | 
			
		||||
            titleResId(R.string.settings_discovery_emails_title)
 | 
			
		||||
@ -190,7 +193,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
                if (emails().isEmpty()) {
 | 
			
		||||
                    settingsInfoItem {
 | 
			
		||||
                        id("emailsEmpty")
 | 
			
		||||
                        helperText(stringProvider.getString(R.string.settings_discovery_no_mails))
 | 
			
		||||
                        helperText(host.stringProvider.getString(R.string.settings_discovery_no_mails))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    emails().forEach { buildEmail(it) }
 | 
			
		||||
@ -202,6 +205,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    private fun buildEmail(pidInfo: PidInfo) {
 | 
			
		||||
        buildThreePid(pidInfo)
 | 
			
		||||
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (pidInfo.isShared is Fail) {
 | 
			
		||||
            buildSharedFail(pidInfo)
 | 
			
		||||
        } else if (pidInfo.isShared() == SharedState.BINDING_IN_PROGRESS) {
 | 
			
		||||
@ -210,14 +214,14 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
                is Loading ->
 | 
			
		||||
                    settingsInformationItem {
 | 
			
		||||
                        id("info${pidInfo.threePid.value}")
 | 
			
		||||
                        colorProvider(colorProvider)
 | 
			
		||||
                        message(stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value))
 | 
			
		||||
                        colorProvider(host.colorProvider)
 | 
			
		||||
                        message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail, pidInfo.threePid.value))
 | 
			
		||||
                    }
 | 
			
		||||
                is Fail    ->
 | 
			
		||||
                    settingsInformationItem {
 | 
			
		||||
                        id("info${pidInfo.threePid.value}")
 | 
			
		||||
                        colorProvider(colorProvider)
 | 
			
		||||
                        message(stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value))
 | 
			
		||||
                        colorProvider(host.colorProvider)
 | 
			
		||||
                        message(host.stringProvider.getString(R.string.settings_discovery_confirm_mail_not_clicked, pidInfo.threePid.value))
 | 
			
		||||
                        textColorId(R.color.riotx_destructive_accent)
 | 
			
		||||
                    }
 | 
			
		||||
                is Success -> Unit /* Cannot happen */
 | 
			
		||||
@ -236,6 +240,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildMsisdnSection(msisdns: Async<List<PidInfo>>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("msisdn")
 | 
			
		||||
            titleResId(R.string.settings_discovery_msisdn_title)
 | 
			
		||||
@ -257,7 +262,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
                if (msisdns().isEmpty()) {
 | 
			
		||||
                    settingsInfoItem {
 | 
			
		||||
                        id("no_msisdn")
 | 
			
		||||
                        helperText(stringProvider.getString(R.string.settings_discovery_no_msisdn))
 | 
			
		||||
                        helperText(host.stringProvider.getString(R.string.settings_discovery_no_msisdn))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    msisdns().forEach { buildMsisdn(it) }
 | 
			
		||||
@ -267,6 +272,7 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildMsisdn(pidInfo: PidInfo) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val phoneNumber = pidInfo.threePid.getFormattedValue()
 | 
			
		||||
 | 
			
		||||
        buildThreePid(pidInfo, phoneNumber)
 | 
			
		||||
@ -289,19 +295,19 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            settingsEditTextItem {
 | 
			
		||||
                id("msisdnVerification${pidInfo.threePid.value}")
 | 
			
		||||
                descriptionText(stringProvider.getString(R.string.settings_text_message_sent, phoneNumber))
 | 
			
		||||
                descriptionText(host.stringProvider.getString(R.string.settings_text_message_sent, phoneNumber))
 | 
			
		||||
                errorText(errorText)
 | 
			
		||||
                inProgress(pidInfo.finalRequest is Loading)
 | 
			
		||||
                interactionListener(object : SettingsEditTextItem.Listener {
 | 
			
		||||
                    override fun onValidate() {
 | 
			
		||||
                        val code = codes[pidInfo.threePid]
 | 
			
		||||
                        val code = host.codes[pidInfo.threePid]
 | 
			
		||||
                        if (pidInfo.threePid is ThreePid.Msisdn && code != null) {
 | 
			
		||||
                            listener?.sendMsisdnVerificationCode(pidInfo.threePid, code)
 | 
			
		||||
                            host.listener?.sendMsisdnVerificationCode(pidInfo.threePid, code)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    override fun onTextChange(text: String) {
 | 
			
		||||
                        codes[pidInfo.threePid] = text
 | 
			
		||||
                        host.codes[pidInfo.threePid] = text
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
@ -310,11 +316,12 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildThreePid(pidInfo: PidInfo, title: String = pidInfo.threePid.value) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsTextButtonSingleLineItem {
 | 
			
		||||
            id(pidInfo.threePid.value)
 | 
			
		||||
            title(title)
 | 
			
		||||
            colorProvider(colorProvider)
 | 
			
		||||
            stringProvider(stringProvider)
 | 
			
		||||
            colorProvider(host.colorProvider)
 | 
			
		||||
            stringProvider(host.stringProvider)
 | 
			
		||||
            when (pidInfo.isShared) {
 | 
			
		||||
                is Loading -> {
 | 
			
		||||
                    buttonIndeterminate(true)
 | 
			
		||||
@ -322,9 +329,9 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
                is Fail    -> {
 | 
			
		||||
                    buttonType(ButtonType.NORMAL)
 | 
			
		||||
                    buttonStyle(ButtonStyle.DESTRUCTIVE)
 | 
			
		||||
                    buttonTitle(stringProvider.getString(R.string.global_retry))
 | 
			
		||||
                    buttonTitle(host.stringProvider.getString(R.string.global_retry))
 | 
			
		||||
                    iconMode(IconMode.ERROR)
 | 
			
		||||
                    buttonClickListener { listener?.onTapRetryToRetrieveBindings() }
 | 
			
		||||
                    buttonClickListener { host.listener?.onTapRetryToRetrieveBindings() }
 | 
			
		||||
                }
 | 
			
		||||
                is Success -> when (pidInfo.isShared()) {
 | 
			
		||||
                    SharedState.SHARED,
 | 
			
		||||
@ -333,9 +340,9 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
                        checked(pidInfo.isShared() == SharedState.SHARED)
 | 
			
		||||
                        switchChangeListener { _, checked ->
 | 
			
		||||
                            if (checked) {
 | 
			
		||||
                                listener?.onTapShare(pidInfo.threePid)
 | 
			
		||||
                                host.listener?.onTapShare(pidInfo.threePid)
 | 
			
		||||
                            } else {
 | 
			
		||||
                                listener?.onTapRevoke(pidInfo.threePid)
 | 
			
		||||
                                host.listener?.onTapRevoke(pidInfo.threePid)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -353,32 +360,34 @@ class DiscoverySettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildSharedFail(pidInfo: PidInfo) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsInformationItem {
 | 
			
		||||
            id("info${pidInfo.threePid.value}")
 | 
			
		||||
            colorProvider(colorProvider)
 | 
			
		||||
            colorProvider(host.colorProvider)
 | 
			
		||||
            textColorId(R.color.vector_error_color)
 | 
			
		||||
            message((pidInfo.isShared as? Fail)?.error?.message ?: "")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildContinueCancel(threePid: ThreePid) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsContinueCancelItem {
 | 
			
		||||
            id("bottom${threePid.value}")
 | 
			
		||||
            continueOnClick {
 | 
			
		||||
                when (threePid) {
 | 
			
		||||
                    is ThreePid.Email  -> {
 | 
			
		||||
                        listener?.checkEmailVerification(threePid)
 | 
			
		||||
                        host.listener?.checkEmailVerification(threePid)
 | 
			
		||||
                    }
 | 
			
		||||
                    is ThreePid.Msisdn -> {
 | 
			
		||||
                        val code = codes[threePid]
 | 
			
		||||
                        val code = host.codes[threePid]
 | 
			
		||||
                        if (code != null) {
 | 
			
		||||
                            listener?.sendMsisdnVerificationCode(threePid, code)
 | 
			
		||||
                            host.listener?.sendMsisdnVerificationCode(threePid, code)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            cancelOnClick {
 | 
			
		||||
                listener?.cancelBinding(threePid)
 | 
			
		||||
                host.listener?.cancelBinding(threePid)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ class BreadcrumbsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val safeViewState = viewState ?: return
 | 
			
		||||
 | 
			
		||||
        val host = this
 | 
			
		||||
        // Add a ZeroItem to avoid automatic scroll when the breadcrumbs are updated from another client
 | 
			
		||||
        zeroItem {
 | 
			
		||||
            id("top")
 | 
			
		||||
@ -57,7 +57,7 @@ class BreadcrumbsController @Inject constructor(
 | 
			
		||||
                    breadcrumbsItem {
 | 
			
		||||
                        id(it.roomId)
 | 
			
		||||
                        hasTypingUsers(it.typingUsers.isNotEmpty())
 | 
			
		||||
                        avatarRenderer(avatarRenderer)
 | 
			
		||||
                        avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                        matrixItem(it.toMatrixItem())
 | 
			
		||||
                        unreadNotificationCount(it.notificationCount)
 | 
			
		||||
                        showHighlighted(it.highlightCount > 0)
 | 
			
		||||
@ -65,7 +65,7 @@ class BreadcrumbsController @Inject constructor(
 | 
			
		||||
                        hasDraft(it.userDrafts.isNotEmpty())
 | 
			
		||||
                        itemClickListener(
 | 
			
		||||
                                DebouncedClickListener({ _ ->
 | 
			
		||||
                                    listener?.onBreadcrumbClicked(it.roomId)
 | 
			
		||||
                                    host.listener?.onBreadcrumbClicked(it.roomId)
 | 
			
		||||
                                })
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -70,10 +70,10 @@ class RoomMessageTouchHelperCallback(private val context: Context,
 | 
			
		||||
    private val minShowDistance = convertToPx(20)
 | 
			
		||||
    private val triggerDelta = convertToPx(20)
 | 
			
		||||
 | 
			
		||||
    override fun onSwiped(viewHolder: EpoxyViewHolder?, direction: Int) {
 | 
			
		||||
    override fun onSwiped(viewHolder: EpoxyViewHolder, direction: Int) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onMove(recyclerView: RecyclerView?, viewHolder: EpoxyViewHolder?, target: EpoxyViewHolder?): Boolean {
 | 
			
		||||
    override fun onMove(recyclerView: RecyclerView, viewHolder: EpoxyViewHolder, target: EpoxyViewHolder): Boolean {
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -61,15 +61,16 @@ class SearchResultController @Inject constructor(
 | 
			
		||||
    override fun buildModels(data: SearchViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
 | 
			
		||||
        val host = this
 | 
			
		||||
        val searchItems = buildSearchResultItems(data)
 | 
			
		||||
 | 
			
		||||
        if (data.hasMoreResult) {
 | 
			
		||||
            loadingItem {
 | 
			
		||||
                // Always use a different id, because we can be notified several times of visibility state changed
 | 
			
		||||
                id("loadMore${idx++}")
 | 
			
		||||
                id("loadMore${host.idx++}")
 | 
			
		||||
                onVisibilityStateChanged { _, _, visibilityState ->
 | 
			
		||||
                    if (visibilityState == VisibilityState.VISIBLE) {
 | 
			
		||||
                        listener?.loadMore()
 | 
			
		||||
                        host.listener?.loadMore()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -78,12 +79,12 @@ class SearchResultController @Inject constructor(
 | 
			
		||||
                // All returned results by the server has been filtered out and there is no more result
 | 
			
		||||
                noResultItem {
 | 
			
		||||
                    id("noResult")
 | 
			
		||||
                    text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                noResultItem {
 | 
			
		||||
                    id("noMoreResult")
 | 
			
		||||
                    text(stringProvider.getString(R.string.no_more_results))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.no_more_results))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -456,9 +456,10 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun LoadingItem_.setVisibilityStateChangedListener(direction: Timeline.Direction): LoadingItem_ {
 | 
			
		||||
        val host = this@TimelineEventController
 | 
			
		||||
        return onVisibilityStateChanged { _, _, visibilityState ->
 | 
			
		||||
            if (visibilityState == VisibilityState.VISIBLE) {
 | 
			
		||||
                callback?.onLoadMore(direction)
 | 
			
		||||
                host.callback?.onLoadMore(direction)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -498,8 +499,9 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
 | 
			
		||||
     * Return true if added
 | 
			
		||||
     */
 | 
			
		||||
    private fun LoadingItem_.addWhenLoading(direction: Timeline.Direction): Boolean {
 | 
			
		||||
        val shouldAdd = timeline?.hasMoreToLoad(direction) ?: false
 | 
			
		||||
        addIf(shouldAdd, this@TimelineEventController)
 | 
			
		||||
        val host = this@TimelineEventController
 | 
			
		||||
        val shouldAdd = host.timeline?.hasMoreToLoad(direction) ?: false
 | 
			
		||||
        addIf(shouldAdd, host)
 | 
			
		||||
        return shouldAdd
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -61,19 +61,20 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
    var listener: MessageActionsEpoxyControllerListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(state: MessageActionState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        // Message preview
 | 
			
		||||
        val date = state.timelineEvent()?.root?.originServerTs
 | 
			
		||||
        val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL)
 | 
			
		||||
        bottomSheetMessagePreviewItem {
 | 
			
		||||
            id("preview")
 | 
			
		||||
            avatarRenderer(avatarRenderer)
 | 
			
		||||
            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
            matrixItem(state.informationData.matrixItem)
 | 
			
		||||
            movementMethod(createLinkMovementMethod(listener))
 | 
			
		||||
            imageContentRenderer(imageContentRenderer)
 | 
			
		||||
            data(state.timelineEvent()?.buildImageContentRendererData(dimensionConverter.dpToPx(66)))
 | 
			
		||||
            userClicked { listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) }
 | 
			
		||||
            body(state.messageBody.linkify(listener))
 | 
			
		||||
            bodyDetails(eventDetailsFormatter.format(state.timelineEvent()?.root))
 | 
			
		||||
            movementMethod(createLinkMovementMethod(host.listener))
 | 
			
		||||
            imageContentRenderer(host.imageContentRenderer)
 | 
			
		||||
            data(state.timelineEvent()?.buildImageContentRendererData(host.dimensionConverter.dpToPx(66)))
 | 
			
		||||
            userClicked { host.listener?.didSelectMenuAction(EventSharedAction.OpenUserProfile(state.informationData.senderId)) }
 | 
			
		||||
            body(state.messageBody.linkify(host.listener))
 | 
			
		||||
            bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root))
 | 
			
		||||
            time(formattedDate)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -94,14 +95,14 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
            bottomSheetSendStateItem {
 | 
			
		||||
                id("send_state")
 | 
			
		||||
                showProgress(true)
 | 
			
		||||
                text(stringProvider.getString(R.string.event_status_sending_message))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.event_status_sending_message))
 | 
			
		||||
            }
 | 
			
		||||
        } else if (sendState == SendState.SENT) {
 | 
			
		||||
            bottomSheetSendStateItem {
 | 
			
		||||
                id("send_state")
 | 
			
		||||
                showProgress(false)
 | 
			
		||||
                drawableStart(R.drawable.ic_message_sent)
 | 
			
		||||
                text(stringProvider.getString(R.string.event_status_sent_message))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.event_status_sent_message))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -110,7 +111,7 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
                bottomSheetSendStateItem {
 | 
			
		||||
                    id("e2e_clear")
 | 
			
		||||
                    showProgress(false)
 | 
			
		||||
                    text(stringProvider.getString(R.string.unencrypted))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.unencrypted))
 | 
			
		||||
                    drawableStart(R.drawable.ic_shield_warning_small)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -119,7 +120,7 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
                bottomSheetSendStateItem {
 | 
			
		||||
                    id("e2e_unverified")
 | 
			
		||||
                    showProgress(false)
 | 
			
		||||
                    text(stringProvider.getString(R.string.encrypted_unverified))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.encrypted_unverified))
 | 
			
		||||
                    drawableStart(R.drawable.ic_shield_warning_small)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -137,12 +138,12 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            bottomSheetQuickReactionsItem {
 | 
			
		||||
                id("quick_reaction")
 | 
			
		||||
                fontProvider(fontProvider)
 | 
			
		||||
                fontProvider(host.fontProvider)
 | 
			
		||||
                texts(state.quickStates()?.map { it.reaction }.orEmpty())
 | 
			
		||||
                selecteds(state.quickStates.invoke().map { it.isSelected })
 | 
			
		||||
                listener(object : BottomSheetQuickReactionsItem.Listener {
 | 
			
		||||
                    override fun didSelect(emoji: String, selected: Boolean) {
 | 
			
		||||
                        listener?.didSelectMenuAction(EventSharedAction.QuickReact(state.eventId, emoji, selected))
 | 
			
		||||
                        host.listener?.didSelectMenuAction(EventSharedAction.QuickReact(state.eventId, emoji, selected))
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
@ -168,7 +169,7 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
                    textRes(action.titleRes)
 | 
			
		||||
                    showExpand(action is EventSharedAction.ReportContent)
 | 
			
		||||
                    expanded(state.expendedReportContentMenu)
 | 
			
		||||
                    listener(View.OnClickListener { listener?.didSelectMenuAction(action) })
 | 
			
		||||
                    listener(View.OnClickListener { host.listener?.didSelectMenuAction(action) })
 | 
			
		||||
                    destructive(action.destructive)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -184,7 +185,7 @@ class MessageActionsEpoxyController @Inject constructor(
 | 
			
		||||
                            subMenuItem(true)
 | 
			
		||||
                            iconRes(actionReport.iconResId)
 | 
			
		||||
                            textRes(actionReport.titleRes)
 | 
			
		||||
                            listener(View.OnClickListener { listener?.didSelectMenuAction(actionReport) })
 | 
			
		||||
                            listener(View.OnClickListener { host.listener?.didSelectMenuAction(actionReport) })
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -30,24 +30,19 @@ import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
 | 
			
		||||
import im.vector.app.databinding.BottomSheetGenericListWithTitleBinding
 | 
			
		||||
import im.vector.app.features.home.room.detail.timeline.action.TimelineEventFragmentArgs
 | 
			
		||||
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
 | 
			
		||||
import im.vector.app.features.html.EventHtmlRenderer
 | 
			
		||||
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Bottom sheet displaying list of edits for a given event ordered by timestamp
 | 
			
		||||
 */
 | 
			
		||||
class ViewEditHistoryBottomSheet :
 | 
			
		||||
class ViewEditHistoryBottomSheet:
 | 
			
		||||
        VectorBaseBottomSheetDialogFragment<BottomSheetGenericListWithTitleBinding>() {
 | 
			
		||||
 | 
			
		||||
    private val viewModel: ViewEditHistoryViewModel by fragmentViewModel(ViewEditHistoryViewModel::class)
 | 
			
		||||
 | 
			
		||||
    @Inject lateinit var viewEditHistoryViewModelFactory: ViewEditHistoryViewModel.Factory
 | 
			
		||||
    @Inject lateinit var eventHtmlRenderer: EventHtmlRenderer
 | 
			
		||||
 | 
			
		||||
    private val epoxyController by lazy {
 | 
			
		||||
        ViewEditHistoryEpoxyController(requireContext(), viewModel.dateFormatter, eventHtmlRenderer)
 | 
			
		||||
    }
 | 
			
		||||
    @Inject lateinit var epoxyController: ViewEditHistoryEpoxyController
 | 
			
		||||
 | 
			
		||||
    override fun injectWith(injector: ScreenComponent) {
 | 
			
		||||
        injector.inject(this)
 | 
			
		||||
 | 
			
		||||
@ -15,9 +15,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package im.vector.app.features.home.room.detail.timeline.edithistory
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.text.Spannable
 | 
			
		||||
import androidx.core.content.ContextCompat
 | 
			
		||||
import com.airbnb.epoxy.TypedEpoxyController
 | 
			
		||||
import com.airbnb.mvrx.Fail
 | 
			
		||||
import com.airbnb.mvrx.Incomplete
 | 
			
		||||
@ -25,6 +23,8 @@ 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.resources.ColorProvider
 | 
			
		||||
import im.vector.app.core.resources.StringProvider
 | 
			
		||||
import im.vector.app.core.ui.list.genericFooterItem
 | 
			
		||||
import im.vector.app.core.ui.list.genericItem
 | 
			
		||||
import im.vector.app.core.ui.list.genericItemHeader
 | 
			
		||||
@ -38,15 +38,20 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
 | 
			
		||||
import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply
 | 
			
		||||
import org.matrix.android.sdk.internal.session.room.send.TextContent
 | 
			
		||||
import java.util.Calendar
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Epoxy controller for edit history list
 | 
			
		||||
 */
 | 
			
		||||
class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
                                     val dateFormatter: VectorDateFormatter,
 | 
			
		||||
                                     val eventHtmlRenderer: EventHtmlRenderer) : TypedEpoxyController<ViewEditHistoryViewState>() {
 | 
			
		||||
class ViewEditHistoryEpoxyController @Inject constructor(
 | 
			
		||||
        private val stringProvider: StringProvider,
 | 
			
		||||
        private val colorProvider: ColorProvider,
 | 
			
		||||
        private val eventHtmlRenderer: EventHtmlRenderer,
 | 
			
		||||
        private val dateFormatter: VectorDateFormatter
 | 
			
		||||
) : TypedEpoxyController<ViewEditHistoryViewState>() {
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(state: ViewEditHistoryViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (state.editList) {
 | 
			
		||||
            is Incomplete -> {
 | 
			
		||||
                genericLoaderItem {
 | 
			
		||||
@ -56,7 +61,7 @@ class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("failure")
 | 
			
		||||
                    text(context.getString(R.string.unknown_error))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.unknown_error))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    -> {
 | 
			
		||||
@ -66,10 +71,11 @@ class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderEvents(sourceEvents: List<Event>, isOriginalReply: Boolean) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (sourceEvents.isEmpty()) {
 | 
			
		||||
            genericItem {
 | 
			
		||||
                id("footer")
 | 
			
		||||
                title(context.getString(R.string.no_message_edits_found))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.no_message_edits_found))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            var lastDate: Calendar? = null
 | 
			
		||||
@ -83,7 +89,7 @@ class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
                    // need to display header with day
 | 
			
		||||
                    genericItemHeader {
 | 
			
		||||
                        id(evDate.hashCode())
 | 
			
		||||
                        text(dateFormatter.format(evDate.timeInMillis, DateFormatKind.EDIT_HISTORY_HEADER))
 | 
			
		||||
                        text(host.dateFormatter.format(evDate.timeInMillis, DateFormatKind.EDIT_HISTORY_HEADER))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                lastDate = evDate
 | 
			
		||||
@ -106,14 +112,14 @@ class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
                                diff_match_patch.Operation.DELETE -> {
 | 
			
		||||
                                    span {
 | 
			
		||||
                                        text = it.text.replace("\n", " ")
 | 
			
		||||
                                        textColor = ContextCompat.getColor(context, R.color.vector_error_color)
 | 
			
		||||
                                        textColor = colorProvider.getColor(R.color.vector_error_color)
 | 
			
		||||
                                        textDecorationLine = "line-through"
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                diff_match_patch.Operation.INSERT -> {
 | 
			
		||||
                                    span {
 | 
			
		||||
                                        text = it.text
 | 
			
		||||
                                        textColor = ContextCompat.getColor(context, R.color.vector_success_color)
 | 
			
		||||
                                        textColor = colorProvider.getColor(R.color.vector_success_color)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                else                              -> {
 | 
			
		||||
@ -127,7 +133,7 @@ class ViewEditHistoryEpoxyController(private val context: Context,
 | 
			
		||||
                }
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id(timelineEvent.eventId)
 | 
			
		||||
                    title(dateFormatter.format(timelineEvent.originServerTs, DateFormatKind.EDIT_HISTORY_ROW))
 | 
			
		||||
                    title(host.dateFormatter.format(timelineEvent.originServerTs, DateFormatKind.EDIT_HISTORY_ROW))
 | 
			
		||||
                    description(spannedDiff ?: body)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,6 @@ import com.airbnb.mvrx.ViewModelContext
 | 
			
		||||
import dagger.assisted.Assisted
 | 
			
		||||
import dagger.assisted.AssistedFactory
 | 
			
		||||
import dagger.assisted.AssistedInject
 | 
			
		||||
import im.vector.app.core.date.VectorDateFormatter
 | 
			
		||||
import im.vector.app.core.platform.EmptyAction
 | 
			
		||||
import im.vector.app.core.platform.EmptyViewEvents
 | 
			
		||||
import im.vector.app.core.platform.VectorViewModel
 | 
			
		||||
@ -37,10 +36,9 @@ import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import java.util.UUID
 | 
			
		||||
 | 
			
		||||
class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted
 | 
			
		||||
                                                           initialState: ViewEditHistoryViewState,
 | 
			
		||||
                                                           val session: Session,
 | 
			
		||||
                                                           val dateFormatter: VectorDateFormatter
 | 
			
		||||
class ViewEditHistoryViewModel @AssistedInject constructor(
 | 
			
		||||
        @Assisted initialState: ViewEditHistoryViewState,
 | 
			
		||||
        private val session: Session
 | 
			
		||||
) : VectorViewModel<ViewEditHistoryViewState, EmptyAction, EmptyViewEvents>(initialState) {
 | 
			
		||||
 | 
			
		||||
    private val roomId = initialState.roomId
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ class ViewReactionsEpoxyController @Inject constructor(
 | 
			
		||||
    var listener: Listener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(state: DisplayReactionsViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (state.mapReactionKeyToMemberList) {
 | 
			
		||||
            is Incomplete -> {
 | 
			
		||||
                genericLoaderItem {
 | 
			
		||||
@ -47,7 +48,7 @@ class ViewReactionsEpoxyController @Inject constructor(
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("failure")
 | 
			
		||||
                    text(stringProvider.getString(R.string.unknown_error))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.unknown_error))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    -> {
 | 
			
		||||
@ -55,9 +56,9 @@ class ViewReactionsEpoxyController @Inject constructor(
 | 
			
		||||
                    reactionInfoSimpleItem {
 | 
			
		||||
                        id(it.eventId)
 | 
			
		||||
                        timeStamp(it.timestamp)
 | 
			
		||||
                        reactionKey(emojiCompatWrapper.safeEmojiSpanify(it.reactionKey))
 | 
			
		||||
                        reactionKey(host.emojiCompatWrapper.safeEmojiSpanify(it.reactionKey))
 | 
			
		||||
                        authorDisplayName(it.authorName ?: it.authorId)
 | 
			
		||||
                        userClicked { listener?.didSelectUser(it.authorId) }
 | 
			
		||||
                        userClicked { host.listener?.didSelectUser(it.authorId) }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -37,25 +37,26 @@ class RoomWidgetsController @Inject constructor(
 | 
			
		||||
    var listener: Listener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(widgets: List<Widget>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (widgets.isEmpty()) {
 | 
			
		||||
            genericFooterItem {
 | 
			
		||||
                id("empty")
 | 
			
		||||
                text(stringProvider.getString(R.string.room_no_active_widgets))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.room_no_active_widgets))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            widgets.forEach {
 | 
			
		||||
                roomWidgetItem {
 | 
			
		||||
                    id(it.widgetId)
 | 
			
		||||
                    widget(it)
 | 
			
		||||
                    widgetClicked { listener?.didSelectWidget(it) }
 | 
			
		||||
                    widgetClicked { host.listener?.didSelectWidget(it) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        genericButtonItem {
 | 
			
		||||
            id("addIntegration")
 | 
			
		||||
            text(stringProvider.getString(R.string.room_manage_integrations))
 | 
			
		||||
            textColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            buttonClickAction(View.OnClickListener { listener?.didSelectManageWidgets() })
 | 
			
		||||
            text(host.stringProvider.getString(R.string.room_manage_integrations))
 | 
			
		||||
            textColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            buttonClickAction(View.OnClickListener { host.listener?.didSelectManageWidgets() })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,11 +33,12 @@ class RoomListFooterController @Inject constructor(
 | 
			
		||||
    var listener: RoomListListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomListViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data?.displayMode) {
 | 
			
		||||
            RoomListDisplayMode.FILTERED -> {
 | 
			
		||||
                filteredRoomFooterItem {
 | 
			
		||||
                    id("filter_footer")
 | 
			
		||||
                    listener(listener)
 | 
			
		||||
                    listener(host.listener)
 | 
			
		||||
                    currentFilter(data.roomFilter)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -45,7 +46,7 @@ class RoomListFooterController @Inject constructor(
 | 
			
		||||
                if (userPreferencesProvider.shouldShowLongClickOnRoomHelp()) {
 | 
			
		||||
                    helpFooterItem {
 | 
			
		||||
                        id("long_click_help")
 | 
			
		||||
                        text(stringProvider.getString(R.string.help_long_click_on_room_for_more_options))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.help_long_click_on_room_for_more_options))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -38,20 +38,21 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(state: RoomListQuickActionsState) {
 | 
			
		||||
        val roomSummary = state.roomSummary() ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
        val showAll = state.mode == RoomListActionsArgs.Mode.FULL
 | 
			
		||||
 | 
			
		||||
        if (showAll) {
 | 
			
		||||
            // Preview, favorite, settings
 | 
			
		||||
            bottomSheetRoomPreviewItem {
 | 
			
		||||
                id("room_preview")
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                matrixItem(roomSummary.toMatrixItem())
 | 
			
		||||
                stringProvider(stringProvider)
 | 
			
		||||
                stringProvider(host.stringProvider)
 | 
			
		||||
                izLowPriority(roomSummary.isLowPriority)
 | 
			
		||||
                izFavorite(roomSummary.isFavorite)
 | 
			
		||||
                settingsClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) }
 | 
			
		||||
                favoriteClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) }
 | 
			
		||||
                lowPriorityClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.LowPriority(roomSummary.roomId)) }
 | 
			
		||||
                settingsClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) }
 | 
			
		||||
                favoriteClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) }
 | 
			
		||||
                lowPriorityClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.LowPriority(roomSummary.roomId)) }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Notifications
 | 
			
		||||
@ -72,6 +73,7 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun RoomListQuickActionsSharedAction.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) {
 | 
			
		||||
        val host = this@RoomListQuickActionsEpoxyController
 | 
			
		||||
        val selected = when (this) {
 | 
			
		||||
            is RoomListQuickActionsSharedAction.NotificationsAllNoisy     -> roomNotificationState == RoomNotificationState.ALL_MESSAGES_NOISY
 | 
			
		||||
            is RoomListQuickActionsSharedAction.NotificationsAll          -> roomNotificationState == RoomNotificationState.ALL_MESSAGES
 | 
			
		||||
@ -85,7 +87,7 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
 | 
			
		||||
            iconRes(iconResId)
 | 
			
		||||
            textRes(titleRes)
 | 
			
		||||
            destructive(this@toBottomSheetItem.destructive)
 | 
			
		||||
            listener(View.OnClickListener { listener?.didSelectMenuAction(this@toBottomSheetItem) })
 | 
			
		||||
            listener(View.OnClickListener { host.listener?.didSelectMenuAction(this@toBottomSheetItem) })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,16 +28,17 @@ class PolicyController @Inject constructor() : TypedEpoxyController<List<Localiz
 | 
			
		||||
    var homeServer: String? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: List<LocalizedFlowDataLoginTermsChecked>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.forEach { entry ->
 | 
			
		||||
            policyItem {
 | 
			
		||||
                id(entry.localizedFlowDataLoginTerms.policyName)
 | 
			
		||||
                checked(entry.checked)
 | 
			
		||||
                title(entry.localizedFlowDataLoginTerms.localizedName)
 | 
			
		||||
                subtitle(homeServer)
 | 
			
		||||
                subtitle(host.homeServer)
 | 
			
		||||
 | 
			
		||||
                clickListener(View.OnClickListener { listener?.openPolicy(entry.localizedFlowDataLoginTerms) })
 | 
			
		||||
                clickListener(View.OnClickListener { host.listener?.openPolicy(entry.localizedFlowDataLoginTerms) })
 | 
			
		||||
                checkChangeListener { _, isChecked ->
 | 
			
		||||
                    listener?.setChecked(entry.localizedFlowDataLoginTerms, isChecked)
 | 
			
		||||
                    host.listener?.setChecked(entry.localizedFlowDataLoginTerms, isChecked)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -45,19 +45,20 @@ class EmojiSearchResultController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: EmojiSearchResultViewState?) {
 | 
			
		||||
        val results = data?.results ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (results.isEmpty()) {
 | 
			
		||||
            if (data.query.isEmpty()) {
 | 
			
		||||
                // display 'Type something to find'
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("type.query.item")
 | 
			
		||||
                    text(stringProvider.getString(R.string.reaction_search_type_hint))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.reaction_search_type_hint))
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // Display no search Results
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("no.results.item")
 | 
			
		||||
                    text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -66,9 +67,9 @@ class EmojiSearchResultController @Inject constructor(
 | 
			
		||||
                emojiSearchResultItem {
 | 
			
		||||
                    id(it.name)
 | 
			
		||||
                    emojiItem(it)
 | 
			
		||||
                    emojiTypeFace(emojiTypeface)
 | 
			
		||||
                    emojiTypeFace(host.emojiTypeface)
 | 
			
		||||
                    currentQuery(data.query)
 | 
			
		||||
                    onClickListener(listener)
 | 
			
		||||
                    onClickListener(host.listener)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
    var callback: Callback? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(viewState: PublicRoomsViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val publicRooms = viewState.publicRooms
 | 
			
		||||
 | 
			
		||||
        val unknownRoomItem = viewState.buildUnknownRoomIfNeeded()
 | 
			
		||||
@ -51,7 +52,7 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
            // No result
 | 
			
		||||
            noResultItem {
 | 
			
		||||
                id("noResult")
 | 
			
		||||
                text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            publicRooms.forEach {
 | 
			
		||||
@ -71,7 +72,7 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
                    }
 | 
			
		||||
                    onVisibilityStateChanged { _, _, visibilityState ->
 | 
			
		||||
                        if (visibilityState == VisibilityState.VISIBLE) {
 | 
			
		||||
                            callback?.loadMore()
 | 
			
		||||
                            host.callback?.loadMore()
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -81,15 +82,16 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
        if (viewState.asyncPublicRoomsRequest is Fail) {
 | 
			
		||||
            errorWithRetryItem {
 | 
			
		||||
                id("error")
 | 
			
		||||
                text(errorFormatter.toHumanReadable(viewState.asyncPublicRoomsRequest.error))
 | 
			
		||||
                listener { callback?.loadMore() }
 | 
			
		||||
                text(host.errorFormatter.toHumanReadable(viewState.asyncPublicRoomsRequest.error))
 | 
			
		||||
                listener { host.callback?.loadMore() }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildPublicRoom(publicRoom: PublicRoom, viewState: PublicRoomsViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        publicRoomItem {
 | 
			
		||||
            avatarRenderer(avatarRenderer)
 | 
			
		||||
            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
            id(publicRoom.roomId)
 | 
			
		||||
            matrixItem(publicRoom.toMatrixItem())
 | 
			
		||||
            roomAlias(publicRoom.getPrimaryAlias())
 | 
			
		||||
@ -107,10 +109,10 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
            joinState(joinState)
 | 
			
		||||
 | 
			
		||||
            joinListener {
 | 
			
		||||
                callback?.onPublicRoomJoin(publicRoom)
 | 
			
		||||
                host.callback?.onPublicRoomJoin(publicRoom)
 | 
			
		||||
            }
 | 
			
		||||
            globalListener {
 | 
			
		||||
                callback?.onPublicRoomClicked(publicRoom, joinState)
 | 
			
		||||
                host.callback?.onPublicRoomClicked(publicRoom, joinState)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -124,13 +126,14 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri
 | 
			
		||||
            isRoomId -> MatrixItem.RoomItem(roomIdOrAlias)
 | 
			
		||||
            else     -> null
 | 
			
		||||
        }
 | 
			
		||||
        val host = this@PublicRoomsController
 | 
			
		||||
        return roomItem?.let {
 | 
			
		||||
            UnknownRoomItem_().apply {
 | 
			
		||||
                id(roomIdOrAlias)
 | 
			
		||||
                matrixItem(it)
 | 
			
		||||
                avatarRenderer(this@PublicRoomsController.avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                globalListener {
 | 
			
		||||
                    callback?.onUnknownRoomClicked(roomIdOrAlias)
 | 
			
		||||
                    host.callback?.onUnknownRoomClicked(roomIdOrAlias)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -45,12 +45,13 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildForm(viewState: CreateRoomViewState, enableFormElement: Boolean) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        formEditableAvatarItem {
 | 
			
		||||
            id("avatar")
 | 
			
		||||
            enabled(enableFormElement)
 | 
			
		||||
            imageUri(viewState.avatarUri)
 | 
			
		||||
            clickListener { listener?.onAvatarChange() }
 | 
			
		||||
            deleteListener { listener?.onAvatarDelete() }
 | 
			
		||||
            clickListener { host.listener?.onAvatarChange() }
 | 
			
		||||
            deleteListener { host.listener?.onAvatarDelete() }
 | 
			
		||||
        }
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("nameSection")
 | 
			
		||||
@ -60,10 +61,10 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
            id("name")
 | 
			
		||||
            enabled(enableFormElement)
 | 
			
		||||
            value(viewState.roomName)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onNameChange(text)
 | 
			
		||||
                host.listener?.onNameChange(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
@ -74,10 +75,10 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
            id("topic")
 | 
			
		||||
            enabled(enableFormElement)
 | 
			
		||||
            value(viewState.roomTopic)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_topic_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_topic_hint))
 | 
			
		||||
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onTopicChange(text)
 | 
			
		||||
                host.listener?.onTopicChange(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
@ -87,13 +88,13 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
        formSwitchItem {
 | 
			
		||||
            id("public")
 | 
			
		||||
            enabled(enableFormElement)
 | 
			
		||||
            title(stringProvider.getString(R.string.create_room_public_title))
 | 
			
		||||
            summary(stringProvider.getString(R.string.create_room_public_description))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.create_room_public_title))
 | 
			
		||||
            summary(host.stringProvider.getString(R.string.create_room_public_description))
 | 
			
		||||
            switchChecked(viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public)
 | 
			
		||||
            showDivider(viewState.roomVisibilityType !is CreateRoomViewState.RoomVisibilityType.Public)
 | 
			
		||||
 | 
			
		||||
            listener { value ->
 | 
			
		||||
                listener?.setIsPublic(value)
 | 
			
		||||
                host.listener?.setIsPublic(value)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (viewState.roomVisibilityType is CreateRoomViewState.RoomVisibilityType.Public) {
 | 
			
		||||
@ -104,11 +105,11 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
                value(viewState.roomVisibilityType.aliasLocalPart)
 | 
			
		||||
                homeServer(":" + viewState.homeServerName)
 | 
			
		||||
                errorMessage(
 | 
			
		||||
                        roomAliasErrorFormatter.format(
 | 
			
		||||
                        host.roomAliasErrorFormatter.format(
 | 
			
		||||
                                (((viewState.asyncCreateRoomRequest as? Fail)?.error) as? CreateRoomFailure.AliasError)?.aliasError)
 | 
			
		||||
                )
 | 
			
		||||
                onTextChange { value ->
 | 
			
		||||
                    listener?.setAliasLocalPart(value)
 | 
			
		||||
                    host.listener?.setAliasLocalPart(value)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -116,43 +117,43 @@ class CreateRoomController @Inject constructor(
 | 
			
		||||
            formSwitchItem {
 | 
			
		||||
                id("encryption")
 | 
			
		||||
                enabled(enableFormElement)
 | 
			
		||||
                title(stringProvider.getString(R.string.create_room_encryption_title))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.create_room_encryption_title))
 | 
			
		||||
                summary(
 | 
			
		||||
                        if (viewState.hsAdminHasDisabledE2E) {
 | 
			
		||||
                            stringProvider.getString(R.string.settings_hs_admin_e2e_disabled)
 | 
			
		||||
                            host.stringProvider.getString(R.string.settings_hs_admin_e2e_disabled)
 | 
			
		||||
                        } else {
 | 
			
		||||
                            stringProvider.getString(R.string.create_room_encryption_description)
 | 
			
		||||
                            host.stringProvider.getString(R.string.create_room_encryption_description)
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
                switchChecked(viewState.isEncrypted)
 | 
			
		||||
 | 
			
		||||
                listener { value ->
 | 
			
		||||
                    listener?.setIsEncrypted(value)
 | 
			
		||||
                    host.listener?.setIsEncrypted(value)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        formAdvancedToggleItem {
 | 
			
		||||
            id("showAdvanced")
 | 
			
		||||
            title(stringProvider.getString(if (viewState.showAdvanced) R.string.hide_advanced else R.string.show_advanced))
 | 
			
		||||
            title(host.stringProvider.getString(if (viewState.showAdvanced) R.string.hide_advanced else R.string.show_advanced))
 | 
			
		||||
            expanded(!viewState.showAdvanced)
 | 
			
		||||
            listener { listener?.toggleShowAdvanced() }
 | 
			
		||||
            listener { host.listener?.toggleShowAdvanced() }
 | 
			
		||||
        }
 | 
			
		||||
        if (viewState.showAdvanced) {
 | 
			
		||||
            formSwitchItem {
 | 
			
		||||
                id("federation")
 | 
			
		||||
                enabled(enableFormElement)
 | 
			
		||||
                title(stringProvider.getString(R.string.create_room_disable_federation_title, viewState.homeServerName))
 | 
			
		||||
                summary(stringProvider.getString(R.string.create_room_disable_federation_description))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.create_room_disable_federation_title, viewState.homeServerName))
 | 
			
		||||
                summary(host.stringProvider.getString(R.string.create_room_disable_federation_description))
 | 
			
		||||
                switchChecked(viewState.disableFederation)
 | 
			
		||||
                showDivider(false)
 | 
			
		||||
                listener { value -> listener?.setDisableFederation(value) }
 | 
			
		||||
                listener { value -> host.listener?.setDisableFederation(value) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        formSubmitButtonItem {
 | 
			
		||||
            id("submit")
 | 
			
		||||
            enabled(enableFormElement)
 | 
			
		||||
            buttonTitleId(R.string.create_room_action_create)
 | 
			
		||||
            buttonClickListener { listener?.submit() }
 | 
			
		||||
            buttonClickListener { host.listener?.submit() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ class RoomDirectoryPickerController @Inject constructor(private val stringProvid
 | 
			
		||||
    var index = 0
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(viewState: RoomDirectoryPickerViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val asyncThirdPartyProtocol = viewState.asyncThirdPartyRequest
 | 
			
		||||
 | 
			
		||||
        when (asyncThirdPartyProtocol) {
 | 
			
		||||
@ -56,24 +57,25 @@ class RoomDirectoryPickerController @Inject constructor(private val stringProvid
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(asyncThirdPartyProtocol.error))
 | 
			
		||||
                    listener { callback?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(asyncThirdPartyProtocol.error))
 | 
			
		||||
                    listener { host.callback?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildDirectory(roomDirectoryData: RoomDirectoryData) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        roomDirectoryItem {
 | 
			
		||||
            id(index++)
 | 
			
		||||
            id(host.index++)
 | 
			
		||||
 | 
			
		||||
            directoryName(roomDirectoryData.displayName)
 | 
			
		||||
 | 
			
		||||
            val description = when {
 | 
			
		||||
                roomDirectoryData.includeAllNetworks      ->
 | 
			
		||||
                    stringProvider.getString(R.string.directory_server_all_rooms_on_server, roomDirectoryData.displayName)
 | 
			
		||||
                    host.stringProvider.getString(R.string.directory_server_all_rooms_on_server, roomDirectoryData.displayName)
 | 
			
		||||
                "Matrix" == roomDirectoryData.displayName ->
 | 
			
		||||
                    stringProvider.getString(R.string.directory_server_native_rooms, roomDirectoryData.displayName)
 | 
			
		||||
                    host.stringProvider.getString(R.string.directory_server_native_rooms, roomDirectoryData.displayName)
 | 
			
		||||
                else                                      ->
 | 
			
		||||
                    null
 | 
			
		||||
            }
 | 
			
		||||
@ -83,7 +85,7 @@ class RoomDirectoryPickerController @Inject constructor(private val stringProvid
 | 
			
		||||
            includeAllNetworks(roomDirectoryData.includeAllNetworks)
 | 
			
		||||
 | 
			
		||||
            globalListener {
 | 
			
		||||
                callback?.onRoomDirectoryClicked(roomDirectoryData)
 | 
			
		||||
                host.callback?.onRoomDirectoryClicked(roomDirectoryData)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -99,6 +99,7 @@ class RoomMemberProfileController @Inject constructor(
 | 
			
		||||
    private fun buildSecuritySection(state: RoomMemberProfileViewState) {
 | 
			
		||||
        // Security
 | 
			
		||||
        buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (state.isRoomEncrypted) {
 | 
			
		||||
            if (state.userMXCrossSigningInfo != null) {
 | 
			
		||||
@ -152,7 +153,7 @@ class RoomMemberProfileController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
                    genericFooterItem {
 | 
			
		||||
                        id("verify_footer")
 | 
			
		||||
                        text(stringProvider.getString(R.string.room_profile_encrypted_subtitle))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.room_profile_encrypted_subtitle))
 | 
			
		||||
                        centered(false)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -170,7 +171,7 @@ class RoomMemberProfileController @Inject constructor(
 | 
			
		||||
        } else {
 | 
			
		||||
            genericFooterItem {
 | 
			
		||||
                id("verify_footer_not_encrypted")
 | 
			
		||||
                text(stringProvider.getString(R.string.room_profile_not_encrypted_subtitle))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.room_profile_not_encrypted_subtitle))
 | 
			
		||||
                centered(false)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -50,16 +50,15 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
    var interactionListener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: DeviceListViewState?) {
 | 
			
		||||
        if (data == null) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data.cryptoDevices) {
 | 
			
		||||
            Uninitialized -> {
 | 
			
		||||
            }
 | 
			
		||||
            is Loading    -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("loading")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.loading))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.loading))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    -> {
 | 
			
		||||
@ -77,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(
 | 
			
		||||
                            stringProvider.getString(
 | 
			
		||||
                            host.stringProvider.getString(
 | 
			
		||||
                                    if (allGreen) R.string.verification_profile_verified else R.string.verification_profile_warning
 | 
			
		||||
                            )
 | 
			
		||||
                    )
 | 
			
		||||
                    description(stringProvider.getString(R.string.verification_conclusion_ok_notice))
 | 
			
		||||
                    description(host.stringProvider.getString(R.string.verification_conclusion_ok_notice))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (vectorPreferences.developerMode()) {
 | 
			
		||||
@ -92,13 +91,13 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("sessions")
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    title(stringProvider.getString(R.string.room_member_profile_sessions_section_title))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.room_member_profile_sessions_section_title))
 | 
			
		||||
                }
 | 
			
		||||
                if (deviceList.isEmpty()) {
 | 
			
		||||
                    // Can this really happen?
 | 
			
		||||
                    genericFooterItem {
 | 
			
		||||
                        id("empty")
 | 
			
		||||
                        text(stringProvider.getString(R.string.search_no_results))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.search_no_results))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Build list of device with status
 | 
			
		||||
@ -107,14 +106,14 @@ 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 (vectorPreferences.developerMode()) {
 | 
			
		||||
                                if (host.vectorPreferences.developerMode()) {
 | 
			
		||||
                                    val seq = span {
 | 
			
		||||
                                        +(device.displayName() ?: device.deviceId)
 | 
			
		||||
                                        +"\n"
 | 
			
		||||
                                        span {
 | 
			
		||||
                                            text = "(${device.deviceId})"
 | 
			
		||||
                                            textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                            textSize = dimensionConverter.spToPx(14)
 | 
			
		||||
                                            textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                            textSize = host.dimensionConverter.spToPx(14)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                    title(seq)
 | 
			
		||||
@ -123,17 +122,17 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            value(
 | 
			
		||||
                                    stringProvider.getString(
 | 
			
		||||
                                    host.stringProvider.getString(
 | 
			
		||||
                                            if (device.isVerified) R.string.trusted else R.string.not_trusted
 | 
			
		||||
                                    )
 | 
			
		||||
                            )
 | 
			
		||||
                            valueColorInt(
 | 
			
		||||
                                    colorProvider.getColor(
 | 
			
		||||
                                    host.colorProvider.getColor(
 | 
			
		||||
                                            if (device.isVerified) R.color.riotx_positive_accent else R.color.riotx_destructive_accent
 | 
			
		||||
                                    )
 | 
			
		||||
                            )
 | 
			
		||||
                            itemClickAction(View.OnClickListener {
 | 
			
		||||
                                interactionListener?.onDeviceSelected(device)
 | 
			
		||||
                                host.interactionListener?.onDeviceSelected(device)
 | 
			
		||||
                            })
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -142,7 +141,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(stringProvider.getString(R.string.room_member_profile_failed_to_get_devices))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.room_member_profile_failed_to_get_devices))
 | 
			
		||||
                    listener {
 | 
			
		||||
                        // TODO
 | 
			
		||||
                    }
 | 
			
		||||
@ -152,6 +151,7 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun addDebugInfo(data: DeviceListViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.memberCrossSigningKey?.masterKey()?.let {
 | 
			
		||||
            genericItemWithValue {
 | 
			
		||||
                id("msk")
 | 
			
		||||
@ -161,8 +161,8 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
                            +"Master Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -177,8 +177,8 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
                            +"User Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -193,8 +193,8 @@ class DeviceListEpoxyController @Inject constructor(private val stringProvider:
 | 
			
		||||
                            +"Self Signed Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,7 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi
 | 
			
		||||
    var interactionListener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: DeviceListViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data?.selectedDevice?.let {
 | 
			
		||||
            val isVerified = it.trustLevel?.isVerified() == true
 | 
			
		||||
            genericItem {
 | 
			
		||||
@ -51,7 +52,7 @@ 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(
 | 
			
		||||
                        stringProvider.getString(
 | 
			
		||||
                        host.stringProvider.getString(
 | 
			
		||||
                                if (isVerified) R.string.verification_profile_verified else R.string.verification_profile_warning
 | 
			
		||||
                        )
 | 
			
		||||
                )
 | 
			
		||||
@ -59,16 +60,16 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi
 | 
			
		||||
            genericFooterItem {
 | 
			
		||||
                id("desc")
 | 
			
		||||
                centered(false)
 | 
			
		||||
                textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                textColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                apply {
 | 
			
		||||
                    if (isVerified) {
 | 
			
		||||
                        // TODO FORMAT
 | 
			
		||||
                        text(stringProvider.getString(R.string.verification_profile_device_verified_because,
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.verification_profile_device_verified_because,
 | 
			
		||||
                                data.userItem?.displayName ?: "",
 | 
			
		||||
                                data.userItem?.id ?: ""))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // TODO what if mine
 | 
			
		||||
                        text(stringProvider.getString(R.string.verification_profile_device_new_signing,
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.verification_profile_device_new_signing,
 | 
			
		||||
                                data.userItem?.displayName ?: "",
 | 
			
		||||
                                data.userItem?.id ?: ""))
 | 
			
		||||
                    }
 | 
			
		||||
@ -84,8 +85,8 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi
 | 
			
		||||
                            +(it.displayName() ?: "")
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = " (${it.deviceId})"
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(14)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(14)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -95,18 +96,18 @@ class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvi
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("warn")
 | 
			
		||||
                    centered(false)
 | 
			
		||||
                    textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    text(stringProvider.getString(R.string.verification_profile_device_untrust_info))
 | 
			
		||||
                    textColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.verification_profile_device_untrust_info))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                bottomSheetVerificationActionItem {
 | 
			
		||||
                    id("verify")
 | 
			
		||||
                    title(stringProvider.getString(R.string.cross_signing_verify_by_emoji))
 | 
			
		||||
                    titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.cross_signing_verify_by_emoji))
 | 
			
		||||
                    titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                    iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    listener {
 | 
			
		||||
                        interactionListener?.onVerifyManually(it)
 | 
			
		||||
                        host.interactionListener?.onVerifyManually(it)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -62,9 +62,8 @@ class RoomProfileController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomProfileViewState?) {
 | 
			
		||||
        if (data == null) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
        val roomSummary = data.roomSummary() ?: return
 | 
			
		||||
 | 
			
		||||
        // Topic
 | 
			
		||||
@ -83,7 +82,7 @@ class RoomProfileController @Inject constructor(
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            override fun onUrlLongClicked(url: String): Boolean {
 | 
			
		||||
                                callback?.onUrlInTopicLongClicked(url)
 | 
			
		||||
                                host.callback?.onUrlInTopicLongClicked(url)
 | 
			
		||||
                                return true
 | 
			
		||||
                            }
 | 
			
		||||
                        }))
 | 
			
		||||
@ -100,7 +99,7 @@ class RoomProfileController @Inject constructor(
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("e2e info")
 | 
			
		||||
            centered(false)
 | 
			
		||||
            text(stringProvider.getString(learnMoreSubtitle))
 | 
			
		||||
            text(host.stringProvider.getString(learnMoreSubtitle))
 | 
			
		||||
        }
 | 
			
		||||
        buildEncryptionAction(data.actionPermissions, roomSummary)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -77,34 +77,36 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildRoomDirectoryVisibility(data: RoomAliasViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data.roomDirectoryVisibility) {
 | 
			
		||||
            Uninitialized -> Unit
 | 
			
		||||
            is Loading    -> Unit
 | 
			
		||||
            is Success    -> {
 | 
			
		||||
                formSwitchItem {
 | 
			
		||||
                    id("roomVisibility")
 | 
			
		||||
                    title(stringProvider.getString(R.string.room_alias_publish_to_directory, data.homeServerName))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.room_alias_publish_to_directory, data.homeServerName))
 | 
			
		||||
                    showDivider(false)
 | 
			
		||||
                    switchChecked(data.roomDirectoryVisibility() == RoomDirectoryVisibility.PUBLIC)
 | 
			
		||||
                    listener {
 | 
			
		||||
                        if (it) {
 | 
			
		||||
                            callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PUBLIC)
 | 
			
		||||
                            host.callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PUBLIC)
 | 
			
		||||
                        } else {
 | 
			
		||||
                            callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PRIVATE)
 | 
			
		||||
                            host.callback?.setRoomDirectoryVisibility(RoomDirectoryVisibility.PRIVATE)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    text(stringProvider.getString(R.string.room_alias_publish_to_directory_error,
 | 
			
		||||
                            errorFormatter.toHumanReadable(data.roomDirectoryVisibility.error)))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.room_alias_publish_to_directory_error,
 | 
			
		||||
                            host.errorFormatter.toHumanReadable(data.roomDirectoryVisibility.error)))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildPublishInfo(data: RoomAliasViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        buildProfileSection(
 | 
			
		||||
                stringProvider.getString(R.string.room_alias_published_alias_title)
 | 
			
		||||
        )
 | 
			
		||||
@ -120,8 +122,8 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
                    profileActionItem {
 | 
			
		||||
                        id("canonical")
 | 
			
		||||
                        title(data.canonicalAlias)
 | 
			
		||||
                        subtitle(stringProvider.getString(R.string.room_alias_published_alias_main))
 | 
			
		||||
                        listener { callback?.openAliasDetail(canonicalAlias) }
 | 
			
		||||
                        subtitle(host.stringProvider.getString(R.string.room_alias_published_alias_main))
 | 
			
		||||
                        listener { host.callback?.openAliasDetail(canonicalAlias) }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -143,7 +145,7 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
                profileActionItem {
 | 
			
		||||
                    id("alt_$idx")
 | 
			
		||||
                    title(altAlias)
 | 
			
		||||
                    listener { callback?.openAliasDetail(altAlias) }
 | 
			
		||||
                    listener { host.callback?.openAliasDetail(altAlias) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -154,14 +156,15 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildPublishManuallyForm(data: RoomAliasViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data.publishManuallyState) {
 | 
			
		||||
            RoomAliasViewState.AddAliasState.Hidden     -> Unit
 | 
			
		||||
            RoomAliasViewState.AddAliasState.Closed     -> {
 | 
			
		||||
                settingsButtonItem {
 | 
			
		||||
                    id("publishManually")
 | 
			
		||||
                    colorProvider(colorProvider)
 | 
			
		||||
                    colorProvider(host.colorProvider)
 | 
			
		||||
                    buttonTitleId(R.string.room_alias_published_alias_add_manually)
 | 
			
		||||
                    buttonClickListener { callback?.toggleManualPublishForm() }
 | 
			
		||||
                    buttonClickListener { host.callback?.toggleManualPublishForm() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is RoomAliasViewState.AddAliasState.Editing -> {
 | 
			
		||||
@ -169,29 +172,30 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
                    id("publishManuallyEdit")
 | 
			
		||||
                    value(data.publishManuallyState.value)
 | 
			
		||||
                    showBottomSeparator(false)
 | 
			
		||||
                    hint(stringProvider.getString(R.string.room_alias_address_hint))
 | 
			
		||||
                    hint(host.stringProvider.getString(R.string.room_alias_address_hint))
 | 
			
		||||
                    inputType(InputType.TYPE_CLASS_TEXT)
 | 
			
		||||
                    onTextChange { text ->
 | 
			
		||||
                        callback?.setNewAlias(text)
 | 
			
		||||
                        host.callback?.setNewAlias(text)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("publishManuallySubmit")
 | 
			
		||||
                    continueText(stringProvider.getString(R.string.room_alias_published_alias_add_manually_submit))
 | 
			
		||||
                    continueOnClick { callback?.addAlias() }
 | 
			
		||||
                    cancelOnClick { callback?.toggleManualPublishForm() }
 | 
			
		||||
                    continueText(host.stringProvider.getString(R.string.room_alias_published_alias_add_manually_submit))
 | 
			
		||||
                    continueOnClick { host.callback?.addAlias() }
 | 
			
		||||
                    cancelOnClick { host.callback?.toggleManualPublishForm() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildLocalInfo(data: RoomAliasViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        buildProfileSection(
 | 
			
		||||
                stringProvider.getString(R.string.room_alias_local_address_title)
 | 
			
		||||
        )
 | 
			
		||||
        settingsInfoItem {
 | 
			
		||||
            id("localInfo")
 | 
			
		||||
            helperText(stringProvider.getString(R.string.room_alias_local_address_subtitle, data.homeServerName))
 | 
			
		||||
            helperText(host.stringProvider.getString(R.string.room_alias_local_address_subtitle, data.homeServerName))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        when (val localAliases = data.localAliases) {
 | 
			
		||||
@ -211,7 +215,7 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
                        profileActionItem {
 | 
			
		||||
                            id("loc_$idx")
 | 
			
		||||
                            title(localAlias)
 | 
			
		||||
                            listener { callback?.openAliasDetail(localAlias) }
 | 
			
		||||
                            listener { host.callback?.openAliasDetail(localAlias) }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -219,7 +223,7 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
            is Fail          -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("alt_error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(localAliases.error))
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(localAliases.error))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -229,14 +233,15 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildAddLocalAlias(data: RoomAliasViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data.newLocalAliasState) {
 | 
			
		||||
            RoomAliasViewState.AddAliasState.Hidden     -> Unit
 | 
			
		||||
            RoomAliasViewState.AddAliasState.Closed     -> {
 | 
			
		||||
                settingsButtonItem {
 | 
			
		||||
                    id("newLocalAliasButton")
 | 
			
		||||
                    colorProvider(colorProvider)
 | 
			
		||||
                    colorProvider(host.colorProvider)
 | 
			
		||||
                    buttonTitleId(R.string.room_alias_local_address_add)
 | 
			
		||||
                    buttonClickListener { callback?.toggleLocalAliasForm() }
 | 
			
		||||
                    buttonClickListener { host.callback?.toggleLocalAliasForm() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is RoomAliasViewState.AddAliasState.Editing -> {
 | 
			
		||||
@ -245,16 +250,16 @@ class RoomAliasController @Inject constructor(
 | 
			
		||||
                    value(data.newLocalAliasState.value)
 | 
			
		||||
                    homeServer(":" + data.homeServerName)
 | 
			
		||||
                    showBottomSeparator(false)
 | 
			
		||||
                    errorMessage(roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
 | 
			
		||||
                    errorMessage(host.roomAliasErrorFormatter.format((data.newLocalAliasState.asyncRequest as? Fail)?.error as? RoomAliasError))
 | 
			
		||||
                    onTextChange { value ->
 | 
			
		||||
                        callback?.setNewLocalAliasLocalPart(value)
 | 
			
		||||
                        host.callback?.setNewLocalAliasLocalPart(value)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("newLocalAliasSubmit")
 | 
			
		||||
                    continueText(stringProvider.getString(R.string.action_add))
 | 
			
		||||
                    continueOnClick { callback?.addLocalAlias() }
 | 
			
		||||
                    cancelOnClick { callback?.toggleLocalAliasForm() }
 | 
			
		||||
                    continueText(host.stringProvider.getString(R.string.action_add))
 | 
			
		||||
                    continueOnClick { host.callback?.addLocalAlias() }
 | 
			
		||||
                    cancelOnClick { host.callback?.toggleLocalAliasForm() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -73,12 +73,13 @@ class RoomAliasBottomSheetController @Inject constructor() : TypedEpoxyControlle
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun RoomAliasBottomSheetSharedAction.toBottomSheetItem(index: Int) {
 | 
			
		||||
        val host = this@RoomAliasBottomSheetController
 | 
			
		||||
        return bottomSheetActionItem {
 | 
			
		||||
            id("action_$index")
 | 
			
		||||
            iconRes(iconResId)
 | 
			
		||||
            textRes(titleRes)
 | 
			
		||||
            destructive(this@toBottomSheetItem.destructive)
 | 
			
		||||
            listener(View.OnClickListener { listener?.didSelectMenuAction(this@toBottomSheetItem) })
 | 
			
		||||
            listener(View.OnClickListener { host.listener?.didSelectMenuAction(this@toBottomSheetItem) })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,7 @@ class RoomBannedMemberListController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomBannedMemberListViewState?) {
 | 
			
		||||
        val bannedList = data?.bannedMemberSummaries?.invoke() ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        val quantityString = stringProvider.getQuantityString(R.plurals.room_settings_banned_users_count, bannedList.size, bannedList.size)
 | 
			
		||||
 | 
			
		||||
@ -74,7 +75,7 @@ class RoomBannedMemberListController @Inject constructor(
 | 
			
		||||
                                profileMatrixItemWithProgress {
 | 
			
		||||
                                    id(roomMember.userId)
 | 
			
		||||
                                    matrixItem(roomMember.toMatrixItem())
 | 
			
		||||
                                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                                    apply {
 | 
			
		||||
                                        if (actionInProgress) {
 | 
			
		||||
                                            inProgress(true)
 | 
			
		||||
@ -83,7 +84,7 @@ class RoomBannedMemberListController @Inject constructor(
 | 
			
		||||
                                            inProgress(false)
 | 
			
		||||
                                            editable(true)
 | 
			
		||||
                                            clickListener { _ ->
 | 
			
		||||
                                                callback?.onUnbanClicked(roomMember)
 | 
			
		||||
                                                host.callback?.onUnbanClicked(roomMember)
 | 
			
		||||
                                            }
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
@ -92,7 +93,7 @@ class RoomBannedMemberListController @Inject constructor(
 | 
			
		||||
                            between = { _, roomMemberBefore ->
 | 
			
		||||
                                dividerItem {
 | 
			
		||||
                                    id("divider_${roomMemberBefore.userId}")
 | 
			
		||||
                                    color(dividerColor)
 | 
			
		||||
                                    color(host.dividerColor)
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,7 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomMemberListViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        roomMemberSummaryFilter.filter = data.filter
 | 
			
		||||
 | 
			
		||||
@ -93,17 +94,17 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
                        profileMatrixItem {
 | 
			
		||||
                            id(roomMember.userId)
 | 
			
		||||
                            matrixItem(roomMember.toMatrixItem())
 | 
			
		||||
                            avatarRenderer(avatarRenderer)
 | 
			
		||||
                            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                            userEncryptionTrustLevel(data.trustLevelMap.invoke()?.get(roomMember.userId))
 | 
			
		||||
                            clickListener { _ ->
 | 
			
		||||
                                callback?.onRoomMemberClicked(roomMember)
 | 
			
		||||
                                host.callback?.onRoomMemberClicked(roomMember)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    between = { _, roomMemberBefore ->
 | 
			
		||||
                        dividerItem {
 | 
			
		||||
                            id("divider_${roomMemberBefore.userId}")
 | 
			
		||||
                            color(dividerColor)
 | 
			
		||||
                            color(host.dividerColor)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
            )
 | 
			
		||||
@ -111,7 +112,7 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
                // Display the threepid invite after the regular invite
 | 
			
		||||
                dividerItem {
 | 
			
		||||
                    id("divider_threepidinvites")
 | 
			
		||||
                    color(dividerColor)
 | 
			
		||||
                    color(host.dividerColor)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                buildThreePidInvites(data)
 | 
			
		||||
@ -130,6 +131,7 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildThreePidInvites(data: RoomMemberListViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data.threePidInvites()
 | 
			
		||||
                ?.filter { it.content.toModel<RoomThirdPartyInviteContent>() != null }
 | 
			
		||||
                ?.join(
 | 
			
		||||
@ -138,11 +140,11 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
                                    ?.let { content ->
 | 
			
		||||
                                        profileMatrixItem {
 | 
			
		||||
                                            id("3pid_$idx")
 | 
			
		||||
                                            matrixItem(content.toMatrixItem())
 | 
			
		||||
                                            avatarRenderer(avatarRenderer)
 | 
			
		||||
                                            matrixItem(MatrixItem.UserItem("@", displayName = content.displayName))
 | 
			
		||||
                                            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                                            editable(data.actionsPermissions.canRevokeThreePidInvite)
 | 
			
		||||
                                            clickListener { _ ->
 | 
			
		||||
                                                callback?.onThreePidInviteClicked(event)
 | 
			
		||||
                                                host.callback?.onThreePidInviteClicked(event)
 | 
			
		||||
                                            }
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
@ -150,13 +152,9 @@ class RoomMemberListController @Inject constructor(
 | 
			
		||||
                        between = { idx, _ ->
 | 
			
		||||
                            dividerItem {
 | 
			
		||||
                                id("divider3_$idx")
 | 
			
		||||
                                color(dividerColor)
 | 
			
		||||
                                color(host.dividerColor)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun RoomThirdPartyInviteContent.toMatrixItem(): MatrixItem {
 | 
			
		||||
        return MatrixItem.UserItem("@", displayName = displayName)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,7 @@ class RoomPermissionsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomPermissionsViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        buildProfileSection(
 | 
			
		||||
                stringProvider.getString(R.string.room_permissions_title)
 | 
			
		||||
        )
 | 
			
		||||
@ -97,17 +98,18 @@ class RoomPermissionsController @Inject constructor(
 | 
			
		||||
            else       -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("loading")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.loading))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.loading))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildPermissions(data: RoomPermissionsViewState, content: PowerLevelsContent) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val editable = data.actionPermissions.canChangePowerLevels
 | 
			
		||||
        settingsInfoItem {
 | 
			
		||||
            id("notice")
 | 
			
		||||
            helperText(stringProvider.getString(if (editable) R.string.room_permissions_notice else R.string.room_permissions_notice_read_only))
 | 
			
		||||
            helperText(host.stringProvider.getString(if (editable) R.string.room_permissions_notice else R.string.room_permissions_notice_read_only))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Useful permissions
 | 
			
		||||
@ -116,9 +118,9 @@ class RoomPermissionsController @Inject constructor(
 | 
			
		||||
        // Toggle
 | 
			
		||||
        formAdvancedToggleItem {
 | 
			
		||||
            id("showAdvanced")
 | 
			
		||||
            title(stringProvider.getString(if (data.showAdvancedPermissions) R.string.hide_advanced else R.string.show_advanced))
 | 
			
		||||
            title(host.stringProvider.getString(if (data.showAdvancedPermissions) R.string.hide_advanced else R.string.show_advanced))
 | 
			
		||||
            expanded(!data.showAdvancedPermissions)
 | 
			
		||||
            listener { callback?.toggleShowAllPermissions() }
 | 
			
		||||
            listener { host.callback?.toggleShowAllPermissions() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Advanced permissions
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,7 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomSettingsViewState?) {
 | 
			
		||||
        val roomSummary = data?.roomSummary?.invoke() ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        formEditableAvatarItem {
 | 
			
		||||
            id("avatar")
 | 
			
		||||
@ -69,7 +70,7 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
            when (val avatarAction = data.avatarAction) {
 | 
			
		||||
                RoomSettingsViewState.AvatarAction.None -> {
 | 
			
		||||
                    // Use the current value
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    // We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
 | 
			
		||||
                    matrixItem(roomSummary.toMatrixItem().copy(avatarUrl = data.currentRoomAvatarUrl))
 | 
			
		||||
                }
 | 
			
		||||
@ -78,8 +79,8 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
                is RoomSettingsViewState.AvatarAction.UpdateAvatar ->
 | 
			
		||||
                    imageUri(avatarAction.newAvatarUri)
 | 
			
		||||
            }
 | 
			
		||||
            clickListener { callback?.onAvatarChange() }
 | 
			
		||||
            deleteListener { callback?.onAvatarDelete() }
 | 
			
		||||
            clickListener { host.callback?.onAvatarChange() }
 | 
			
		||||
            deleteListener { host.callback?.onAvatarDelete() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buildProfileSection(
 | 
			
		||||
@ -90,10 +91,10 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
            id("name")
 | 
			
		||||
            enabled(data.actionPermissions.canChangeName)
 | 
			
		||||
            value(data.newName ?: roomSummary.displayName)
 | 
			
		||||
            hint(stringProvider.getString(R.string.room_settings_name_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.room_settings_name_hint))
 | 
			
		||||
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                callback?.onNameChanged(text)
 | 
			
		||||
                host.callback?.onNameChanged(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -101,10 +102,10 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
            id("topic")
 | 
			
		||||
            enabled(data.actionPermissions.canChangeTopic)
 | 
			
		||||
            value(data.newTopic ?: roomSummary.topic)
 | 
			
		||||
            hint(stringProvider.getString(R.string.room_settings_topic_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.room_settings_topic_hint))
 | 
			
		||||
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                callback?.onTopicChanged(text)
 | 
			
		||||
                host.callback?.onTopicChanged(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -134,10 +135,10 @@ class RoomSettingsController @Inject constructor(
 | 
			
		||||
            // add guest access option?
 | 
			
		||||
            formSwitchItem {
 | 
			
		||||
                id("guest_access")
 | 
			
		||||
                title(stringProvider.getString(R.string.room_settings_guest_access_title))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.room_settings_guest_access_title))
 | 
			
		||||
                switchChecked(guestAccess == GuestAccess.CanJoin)
 | 
			
		||||
                listener {
 | 
			
		||||
                    callback?.onToggleGuestAccess()
 | 
			
		||||
                    host.callback?.onToggleGuestAccess()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -49,16 +49,17 @@ class UploadsFileController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomUploadsViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        buildFileItems(data.fileEvents)
 | 
			
		||||
 | 
			
		||||
        if (data.hasMore) {
 | 
			
		||||
            loadingItem {
 | 
			
		||||
                // Always use a different id, because we can be notified several times of visibility state changed
 | 
			
		||||
                id("loadMore${idx++}")
 | 
			
		||||
                id("loadMore${host.idx++}")
 | 
			
		||||
                onVisibilityStateChanged { _, _, visibilityState ->
 | 
			
		||||
                    if (visibilityState == VisibilityState.VISIBLE) {
 | 
			
		||||
                        listener?.loadMore()
 | 
			
		||||
                        host.listener?.loadMore()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -66,24 +67,25 @@ class UploadsFileController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildFileItems(fileEvents: List<UploadEvent>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        fileEvents.forEach { uploadEvent ->
 | 
			
		||||
            uploadsFileItem {
 | 
			
		||||
                id(uploadEvent.eventId)
 | 
			
		||||
                title(uploadEvent.contentWithAttachmentContent.body)
 | 
			
		||||
                subtitle(stringProvider.getString(R.string.uploads_files_subtitle,
 | 
			
		||||
                subtitle(host.stringProvider.getString(R.string.uploads_files_subtitle,
 | 
			
		||||
                        uploadEvent.senderInfo.disambiguatedDisplayName,
 | 
			
		||||
                        dateFormatter.format(uploadEvent.root.originServerTs, DateFormatKind.DEFAULT_DATE_AND_TIME)))
 | 
			
		||||
                        host.dateFormatter.format(uploadEvent.root.originServerTs, DateFormatKind.DEFAULT_DATE_AND_TIME)))
 | 
			
		||||
                listener(object : UploadsFileItem.Listener {
 | 
			
		||||
                    override fun onItemClicked() {
 | 
			
		||||
                        listener?.onOpenClicked(uploadEvent)
 | 
			
		||||
                        host.listener?.onOpenClicked(uploadEvent)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    override fun onDownloadClicked() {
 | 
			
		||||
                        listener?.onDownloadClicked(uploadEvent)
 | 
			
		||||
                        host.listener?.onDownloadClicked(uploadEvent)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    override fun onShareClicked() {
 | 
			
		||||
                        listener?.onShareClicked(uploadEvent)
 | 
			
		||||
                        host.listener?.onShareClicked(uploadEvent)
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -60,16 +60,17 @@ class UploadsMediaController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomUploadsViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        buildMediaItems(data.mediaEvents)
 | 
			
		||||
 | 
			
		||||
        if (data.hasMore) {
 | 
			
		||||
            squareLoadingItem {
 | 
			
		||||
                // Always use a different id, because we can be notified several times of visibility state changed
 | 
			
		||||
                id("loadMore${idx++}")
 | 
			
		||||
                id("loadMore${host.idx++}")
 | 
			
		||||
                onVisibilityStateChanged { _, _, visibilityState ->
 | 
			
		||||
                    if (visibilityState == VisibilityState.VISIBLE) {
 | 
			
		||||
                        listener?.loadMore()
 | 
			
		||||
                        host.listener?.loadMore()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -77,17 +78,18 @@ class UploadsMediaController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildMediaItems(mediaEvents: List<UploadEvent>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        mediaEvents.forEach { uploadEvent ->
 | 
			
		||||
            when (uploadEvent.contentWithAttachmentContent.msgType) {
 | 
			
		||||
                MessageType.MSGTYPE_IMAGE -> {
 | 
			
		||||
                    val data = uploadEvent.toImageContentRendererData() ?: return@forEach
 | 
			
		||||
                    uploadsImageItem {
 | 
			
		||||
                        id(uploadEvent.eventId)
 | 
			
		||||
                        imageContentRenderer(imageContentRenderer)
 | 
			
		||||
                        imageContentRenderer(host.imageContentRenderer)
 | 
			
		||||
                        data(data)
 | 
			
		||||
                        listener(object : UploadsImageItem.Listener {
 | 
			
		||||
                            override fun onItemClicked(view: View, data: ImageContentRenderer.Data) {
 | 
			
		||||
                                listener?.onOpenImageClicked(view, data)
 | 
			
		||||
                                host.listener?.onOpenImageClicked(view, data)
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                    }
 | 
			
		||||
@ -96,11 +98,11 @@ class UploadsMediaController @Inject constructor(
 | 
			
		||||
                    val data = uploadEvent.toVideoContentRendererData() ?: return@forEach
 | 
			
		||||
                    uploadsVideoItem {
 | 
			
		||||
                        id(uploadEvent.eventId)
 | 
			
		||||
                        imageContentRenderer(imageContentRenderer)
 | 
			
		||||
                        imageContentRenderer(host.imageContentRenderer)
 | 
			
		||||
                        data(data)
 | 
			
		||||
                        listener(object : UploadsVideoItem.Listener {
 | 
			
		||||
                            override fun onItemClicked(view: View, data: VideoContentRenderer.Data) {
 | 
			
		||||
                                listener?.onOpenVideoClicked(view, data)
 | 
			
		||||
                                host.listener?.onOpenVideoClicked(view, data)
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -42,18 +42,19 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: CrossSigningSettingsViewState?) {
 | 
			
		||||
        if (data == null) return
 | 
			
		||||
        val host = this
 | 
			
		||||
        when {
 | 
			
		||||
            data.xSigningKeyCanSign        -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("can")
 | 
			
		||||
                    titleIconResourceId(R.drawable.ic_shield_trusted)
 | 
			
		||||
                    title(stringProvider.getString(R.string.encryption_information_dg_xsigning_complete))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_complete))
 | 
			
		||||
                }
 | 
			
		||||
                genericButtonItem {
 | 
			
		||||
                    id("Reset")
 | 
			
		||||
                    text(stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    buttonClickAction(DebouncedClickListener({
 | 
			
		||||
                        interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                        host.interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                    }))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -61,13 +62,13 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("trusted")
 | 
			
		||||
                    titleIconResourceId(R.drawable.ic_shield_custom)
 | 
			
		||||
                    title(stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_trusted))
 | 
			
		||||
                }
 | 
			
		||||
                genericButtonItem {
 | 
			
		||||
                    id("Reset")
 | 
			
		||||
                    text(stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    buttonClickAction(DebouncedClickListener({
 | 
			
		||||
                        interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                        host.interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                    }))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -75,27 +76,27 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("enable")
 | 
			
		||||
                    titleIconResourceId(R.drawable.ic_shield_black)
 | 
			
		||||
                    title(stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_not_trusted))
 | 
			
		||||
                }
 | 
			
		||||
                genericButtonItem {
 | 
			
		||||
                    id("Reset")
 | 
			
		||||
                    text(stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.reset_cross_signing))
 | 
			
		||||
                    buttonClickAction(DebouncedClickListener({
 | 
			
		||||
                        interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                        host.interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                    }))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else                           -> {
 | 
			
		||||
                genericItem {
 | 
			
		||||
                    id("not")
 | 
			
		||||
                    title(stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.encryption_information_dg_xsigning_disabled))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                genericPositiveButtonItem {
 | 
			
		||||
                    id("Initialize")
 | 
			
		||||
                    text(stringProvider.getString(R.string.initialize_cross_signing))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.initialize_cross_signing))
 | 
			
		||||
                    buttonClickAction(DebouncedClickListener({
 | 
			
		||||
                        interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                        host.interactionListener?.didTapInitializeCrossSigning()
 | 
			
		||||
                    }))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -112,8 +113,8 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
                            +"Master Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -128,8 +129,8 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
                            +"User Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -144,8 +145,8 @@ class CrossSigningSettingsController @Inject constructor(
 | 
			
		||||
                            +"Self Signed Key:\n"
 | 
			
		||||
                            span {
 | 
			
		||||
                                text = it.unpaddedBase64PublicKey ?: ""
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = dimensionConverter.spToPx(12)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                textSize = host.dimensionConverter.spToPx(12)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
@ -80,6 +80,7 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
        val isMine = data.isMine
 | 
			
		||||
        val currentSessionIsTrusted = data.accountCrossSigningIsTrusted
 | 
			
		||||
        Timber.v("handleE2EWithCrossSigning $isMine, $cryptoDeviceInfo, $shield")
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (isMine) {
 | 
			
		||||
            if (currentSessionIsTrusted) {
 | 
			
		||||
@ -87,8 +88,8 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
                    id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    titleIconResourceId(shield)
 | 
			
		||||
                    title(stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                    description(stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                    description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
                }
 | 
			
		||||
            } else if (data.canVerifySession) {
 | 
			
		||||
                // You need to complete security, only if there are other session(s) available, or if 4S contains secrets
 | 
			
		||||
@ -96,11 +97,11 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
                    id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                    style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                    titleIconResourceId(shield)
 | 
			
		||||
                    title(stringProvider.getString(R.string.crosssigning_verify_this_session))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.crosssigning_verify_this_session))
 | 
			
		||||
                    if (data.hasOtherSessions) {
 | 
			
		||||
                        description(stringProvider.getString(R.string.confirm_your_identity))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.confirm_your_identity))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        description(stringProvider.getString(R.string.confirm_your_identity_quad_s))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.confirm_your_identity_quad_s))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -116,16 +117,16 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
                        id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                        style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                        titleIconResourceId(shield)
 | 
			
		||||
                        title(stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                        description(stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
                        title(host.stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    genericItem {
 | 
			
		||||
                        id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                        titleIconResourceId(shield)
 | 
			
		||||
                        style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                        title(stringProvider.getString(R.string.encryption_information_not_verified))
 | 
			
		||||
                        description(stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc))
 | 
			
		||||
                        title(host.stringProvider.getString(R.string.encryption_information_not_verified))
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc))
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -145,12 +146,12 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("completeSecurity")
 | 
			
		||||
                title(stringProvider.getString(R.string.crosssigning_verify_this_session))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.crosssigning_verify_this_session))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                listener {
 | 
			
		||||
                    callback?.onAction(DevicesAction.CompleteSecurity)
 | 
			
		||||
                    host.callback?.onAction(DevicesAction.CompleteSecurity)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!isMine) {
 | 
			
		||||
@ -165,6 +166,7 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun handleE2EInLegacy(data: DeviceVerificationInfoBottomSheetViewState, cryptoDeviceInfo: CryptoDeviceInfo, shield: Int) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        // ==== Legacy
 | 
			
		||||
        val isMine = data.isMine
 | 
			
		||||
 | 
			
		||||
@ -174,16 +176,16 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
                id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                titleIconResourceId(shield)
 | 
			
		||||
                title(stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                description(stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.encryption_information_verified))
 | 
			
		||||
                description(host.stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            genericItem {
 | 
			
		||||
                id("trust${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                titleIconResourceId(shield)
 | 
			
		||||
                style(ItemStyle.BIG_TEXT)
 | 
			
		||||
                title(stringProvider.getString(R.string.encryption_information_not_verified))
 | 
			
		||||
                description(stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.encryption_information_not_verified))
 | 
			
		||||
                description(host.stringProvider.getString(R.string.settings_active_sessions_unverified_device_desc))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -203,29 +205,30 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("verify${cryptoDeviceInfo.deviceId}")
 | 
			
		||||
                title(stringProvider.getString(R.string.verification_verify_device))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.verification_verify_device))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                listener {
 | 
			
		||||
                    callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId))
 | 
			
		||||
                    host.callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun addVerifyActions(cryptoDeviceInfo: CryptoDeviceInfo) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        dividerItem {
 | 
			
		||||
            id("verifyDiv")
 | 
			
		||||
        }
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("verify_text")
 | 
			
		||||
            title(stringProvider.getString(R.string.cross_signing_verify_by_text))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.cross_signing_verify_by_text))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            listener {
 | 
			
		||||
                callback?.onAction(DevicesAction.VerifyMyDeviceManually(cryptoDeviceInfo.deviceId))
 | 
			
		||||
                host.callback?.onAction(DevicesAction.VerifyMyDeviceManually(cryptoDeviceInfo.deviceId))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        dividerItem {
 | 
			
		||||
@ -233,17 +236,18 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
        }
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("verify_emoji")
 | 
			
		||||
            title(stringProvider.getString(R.string.cross_signing_verify_by_emoji))
 | 
			
		||||
            titleColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.cross_signing_verify_by_emoji))
 | 
			
		||||
            titleColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            iconColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
            listener {
 | 
			
		||||
                callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId))
 | 
			
		||||
                host.callback?.onAction(DevicesAction.VerifyMyDevice(cryptoDeviceInfo.deviceId))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun addGenericDeviceManageActions(data: DeviceVerificationInfoBottomSheetViewState, deviceId: String) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        // Offer delete session if not me
 | 
			
		||||
        if (!data.isMine) {
 | 
			
		||||
            // Add the delete option
 | 
			
		||||
@ -252,12 +256,12 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
            }
 | 
			
		||||
            bottomSheetVerificationActionItem {
 | 
			
		||||
                id("delete")
 | 
			
		||||
                title(stringProvider.getString(R.string.settings_active_sessions_signout_device))
 | 
			
		||||
                titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.settings_active_sessions_signout_device))
 | 
			
		||||
                titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
                iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent))
 | 
			
		||||
                listener {
 | 
			
		||||
                    callback?.onAction(DevicesAction.Delete(deviceId))
 | 
			
		||||
                    host.callback?.onAction(DevicesAction.Delete(deviceId))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -268,17 +272,18 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
        }
 | 
			
		||||
        bottomSheetVerificationActionItem {
 | 
			
		||||
            id("rename")
 | 
			
		||||
            title(stringProvider.getString(R.string.rename))
 | 
			
		||||
            titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.rename))
 | 
			
		||||
            titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            iconRes(R.drawable.ic_arrow_right)
 | 
			
		||||
            iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            listener {
 | 
			
		||||
                callback?.onAction(DevicesAction.PromptRename(deviceId))
 | 
			
		||||
                host.callback?.onAction(DevicesAction.PromptRename(deviceId))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun handleNonE2EDevice(data: DeviceVerificationInfoBottomSheetViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val info = data.deviceInfo.invoke() ?: return
 | 
			
		||||
        genericItem {
 | 
			
		||||
            id("info${info.deviceId}")
 | 
			
		||||
@ -288,7 +293,7 @@ class DeviceVerificationInfoBottomSheetController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("infoCrypto${info.deviceId}")
 | 
			
		||||
            text(stringProvider.getString(R.string.settings_failed_to_get_crypto_device_info))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.settings_failed_to_get_crypto_device_info))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        info.deviceId?.let { addGenericDeviceManageActions(data, it) }
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,7 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildDevicesModels(state: DevicesViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (val devices = state.devices) {
 | 
			
		||||
            is Loading,
 | 
			
		||||
            is Uninitialized ->
 | 
			
		||||
@ -70,8 +71,8 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
            is Fail          ->
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(devices.error))
 | 
			
		||||
                    listener { callback?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(devices.error))
 | 
			
		||||
                    listener { host.callback?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            is Success       ->
 | 
			
		||||
                buildDevicesList(devices(), state.myDeviceId, !state.hasAccountCrossSigning, state.accountCrossSigningIsTrusted)
 | 
			
		||||
@ -82,6 +83,7 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
                                 myDeviceId: String,
 | 
			
		||||
                                 legacyMode: Boolean,
 | 
			
		||||
                                 currentSessionCrossTrusted: Boolean) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        devices
 | 
			
		||||
                .firstOrNull {
 | 
			
		||||
                    it.deviceInfo.deviceId == myDeviceId
 | 
			
		||||
@ -90,21 +92,21 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
                    // Current device
 | 
			
		||||
                    genericItemHeader {
 | 
			
		||||
                        id("current")
 | 
			
		||||
                        text(stringProvider.getString(R.string.devices_current_device))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.devices_current_device))
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    deviceItem {
 | 
			
		||||
                        id("myDevice${deviceInfo.deviceId}")
 | 
			
		||||
                        legacyMode(legacyMode)
 | 
			
		||||
                        trustedSession(currentSessionCrossTrusted)
 | 
			
		||||
                        dimensionConverter(dimensionConverter)
 | 
			
		||||
                        colorProvider(colorProvider)
 | 
			
		||||
                        detailedMode(vectorPreferences.developerMode())
 | 
			
		||||
                        dimensionConverter(host.dimensionConverter)
 | 
			
		||||
                        colorProvider(host.colorProvider)
 | 
			
		||||
                        detailedMode(host.vectorPreferences.developerMode())
 | 
			
		||||
                        deviceInfo(deviceInfo)
 | 
			
		||||
                        currentDevice(true)
 | 
			
		||||
                        e2eCapable(true)
 | 
			
		||||
                        lastSeenFormatted(dateFormatter.format(deviceInfo.lastSeenTs, DateFormatKind.DEFAULT_DATE_AND_TIME))
 | 
			
		||||
                        itemClickAction { callback?.onDeviceClicked(deviceInfo) }
 | 
			
		||||
                        lastSeenFormatted(host.dateFormatter.format(deviceInfo.lastSeenTs, DateFormatKind.DEFAULT_DATE_AND_TIME))
 | 
			
		||||
                        itemClickAction { host.callback?.onDeviceClicked(deviceInfo) }
 | 
			
		||||
                        trusted(DeviceTrustLevel(currentSessionCrossTrusted, true))
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -126,7 +128,7 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
        if (devices.size > 1) {
 | 
			
		||||
            genericItemHeader {
 | 
			
		||||
                id("others")
 | 
			
		||||
                text(stringProvider.getString(R.string.devices_other_devices))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.devices_other_devices))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            devices
 | 
			
		||||
@ -140,12 +142,12 @@ class DevicesController @Inject constructor(private val errorFormatter: ErrorFor
 | 
			
		||||
                            id("device$idx")
 | 
			
		||||
                            legacyMode(legacyMode)
 | 
			
		||||
                            trustedSession(currentSessionCrossTrusted)
 | 
			
		||||
                            dimensionConverter(dimensionConverter)
 | 
			
		||||
                            colorProvider(colorProvider)
 | 
			
		||||
                            detailedMode(vectorPreferences.developerMode())
 | 
			
		||||
                            dimensionConverter(host.dimensionConverter)
 | 
			
		||||
                            colorProvider(host.colorProvider)
 | 
			
		||||
                            detailedMode(host.vectorPreferences.developerMode())
 | 
			
		||||
                            deviceInfo(deviceInfo)
 | 
			
		||||
                            currentDevice(false)
 | 
			
		||||
                            itemClickAction { callback?.onDeviceClicked(deviceInfo) }
 | 
			
		||||
                            itemClickAction { host.callback?.onDeviceClicked(deviceInfo) }
 | 
			
		||||
                            e2eCapable(cryptoInfo != null)
 | 
			
		||||
                            trusted(cryptoInfo?.trustLevel)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -43,11 +43,12 @@ class AccountDataEpoxyController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: AccountDataViewState?) {
 | 
			
		||||
        if (data == null) return
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (data.accountData) {
 | 
			
		||||
            is Loading -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("loading")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.loading))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.loading))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Fail    -> {
 | 
			
		||||
@ -61,7 +62,7 @@ class AccountDataEpoxyController @Inject constructor(
 | 
			
		||||
                if (dataList.isEmpty()) {
 | 
			
		||||
                    genericFooterItem {
 | 
			
		||||
                        id("noResults")
 | 
			
		||||
                        text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    dataList.forEach { accountData ->
 | 
			
		||||
@ -69,10 +70,10 @@ class AccountDataEpoxyController @Inject constructor(
 | 
			
		||||
                            id(accountData.type)
 | 
			
		||||
                            title(accountData.type)
 | 
			
		||||
                            itemClickAction(DebouncedClickListener({
 | 
			
		||||
                                interactionListener?.didTap(accountData)
 | 
			
		||||
                                host.interactionListener?.didTap(accountData)
 | 
			
		||||
                            }))
 | 
			
		||||
                            itemLongClickAction(View.OnLongClickListener {
 | 
			
		||||
                                interactionListener?.didLongTap(accountData)
 | 
			
		||||
                                host.interactionListener?.didLongTap(accountData)
 | 
			
		||||
                                true
 | 
			
		||||
                            })
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -54,10 +54,11 @@ class GossipingTrailPagedEpoxyController @Inject constructor(
 | 
			
		||||
    var interactionListener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildItemModel(currentPosition: Int, item: Event?): EpoxyModel<*> {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val event = item ?: return GenericItem_().apply { id(currentPosition) }
 | 
			
		||||
        return GenericItem_().apply {
 | 
			
		||||
            id(event.hashCode())
 | 
			
		||||
            itemClickAction(GenericItem.Action("view").apply { perform = Runnable { interactionListener?.didTap(event) } })
 | 
			
		||||
            itemClickAction(GenericItem.Action("view").apply { perform = Runnable { host.interactionListener?.didTap(event) } })
 | 
			
		||||
            title(
 | 
			
		||||
                    if (event.isEncrypted()) {
 | 
			
		||||
                        "${event.getClearType()} [encrypted]"
 | 
			
		||||
@ -67,7 +68,7 @@ class GossipingTrailPagedEpoxyController @Inject constructor(
 | 
			
		||||
            )
 | 
			
		||||
            description(
 | 
			
		||||
                    span {
 | 
			
		||||
                        +vectorDateFormatter.format(event.ageLocalTs, DateFormatKind.DEFAULT_DATE_AND_TIME)
 | 
			
		||||
                        +host.vectorDateFormatter.format(event.ageLocalTs, DateFormatKind.DEFAULT_DATE_AND_TIME)
 | 
			
		||||
                        span("\nfrom: ") {
 | 
			
		||||
                            textStyle = "bold"
 | 
			
		||||
                        }
 | 
			
		||||
@ -98,7 +99,7 @@ class GossipingTrailPagedEpoxyController @Inject constructor(
 | 
			
		||||
                                val content = event.getClearContent().toModel<ForwardedRoomKeyContent>()
 | 
			
		||||
                                if (event.mxDecryptionResult == null) {
 | 
			
		||||
                                    span("**Failed to Decrypt** ${event.mCryptoError}") {
 | 
			
		||||
                                        textColor = colorProvider.getColor(R.color.vector_error_color)
 | 
			
		||||
                                        textColor = host.colorProvider.getColor(R.color.vector_error_color)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                span("\nsessionId:") {
 | 
			
		||||
@ -157,7 +158,7 @@ class GossipingTrailPagedEpoxyController @Inject constructor(
 | 
			
		||||
                                +"${content?.requestingDeviceId}"
 | 
			
		||||
                            } else if (event.getClearType() == EventType.ENCRYPTED) {
 | 
			
		||||
                                span("**Failed to Decrypt** ${event.mCryptoError}") {
 | 
			
		||||
                                        textColor = colorProvider.getColor(R.color.vector_error_color)
 | 
			
		||||
                                        textColor = host.colorProvider.getColor(R.color.vector_error_color)
 | 
			
		||||
                                    }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ class IncomingKeyRequestPagedController @Inject constructor(
 | 
			
		||||
    var interactionListener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildItemModel(currentPosition: Int, item: IncomingRoomKeyRequest?): EpoxyModel<*> {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val roomKeyRequest = item ?: return GenericItem_().apply { id(currentPosition) }
 | 
			
		||||
 | 
			
		||||
        return GenericItem_().apply {
 | 
			
		||||
@ -51,7 +52,7 @@ class IncomingKeyRequestPagedController @Inject constructor(
 | 
			
		||||
                            textStyle = "bold"
 | 
			
		||||
                        }
 | 
			
		||||
                        span("${roomKeyRequest.userId}")
 | 
			
		||||
                        +vectorDateFormatter.format(roomKeyRequest.localCreationTimestamp, DateFormatKind.DEFAULT_DATE_AND_TIME)
 | 
			
		||||
                        +host.vectorDateFormatter.format(roomKeyRequest.localCreationTimestamp, DateFormatKind.DEFAULT_DATE_AND_TIME)
 | 
			
		||||
                        span("\nsessionId:") {
 | 
			
		||||
                            textStyle = "bold"
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,7 @@ class HomeserverSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: HomeServerSettingsViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        buildHeader(data)
 | 
			
		||||
        buildCapabilities(data)
 | 
			
		||||
@ -58,8 +59,8 @@ class HomeserverSettingsController @Inject constructor(
 | 
			
		||||
            is Fail          ->
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("error")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(federationVersion.error))
 | 
			
		||||
                    listener { callback?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(federationVersion.error))
 | 
			
		||||
                    listener { host.callback?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            is Success       ->
 | 
			
		||||
                buildFederationVersion(federationVersion())
 | 
			
		||||
@ -101,6 +102,7 @@ class HomeserverSettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildCapabilities(data: HomeServerSettingsViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("uploadTitle")
 | 
			
		||||
            titleResId(R.string.settings_server_upload_size_title)
 | 
			
		||||
@ -113,7 +115,7 @@ class HomeserverSettingsController @Inject constructor(
 | 
			
		||||
            if (limit == HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN) {
 | 
			
		||||
                helperTextResId(R.string.settings_server_upload_size_unknown)
 | 
			
		||||
            } else {
 | 
			
		||||
                helperText(stringProvider.getString(R.string.settings_server_upload_size_content, "${limit / 1048576L} MB"))
 | 
			
		||||
                helperText(host.stringProvider.getString(R.string.settings_server_upload_size_content, "${limit / 1048576L} MB"))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -46,18 +46,19 @@ class IgnoredUsersController @Inject constructor(private val stringProvider: Str
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildIgnoredUserModels(users: List<User>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (users.isEmpty()) {
 | 
			
		||||
            noResultItem {
 | 
			
		||||
                id("empty")
 | 
			
		||||
                text(stringProvider.getString(R.string.no_ignored_users))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.no_ignored_users))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            users.forEach { user ->
 | 
			
		||||
                userItem {
 | 
			
		||||
                    id(user.userId)
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    matrixItem(user.toMatrixItem())
 | 
			
		||||
                    itemClickAction { callback?.onUserIdClicked(user.userId) }
 | 
			
		||||
                    itemClickAction { host.callback?.onUserIdClicked(user.userId) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -40,35 +40,36 @@ class LocalePickerController @Inject constructor(
 | 
			
		||||
    @ExperimentalStdlibApi
 | 
			
		||||
    override fun buildModels(data: LocalePickerViewState?) {
 | 
			
		||||
        val list = data?.locales ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        profileSectionItem {
 | 
			
		||||
            id("currentTitle")
 | 
			
		||||
            title(stringProvider.getString(R.string.choose_locale_current_locale_title))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.choose_locale_current_locale_title))
 | 
			
		||||
        }
 | 
			
		||||
        localeItem {
 | 
			
		||||
            id(data.currentLocale.toString())
 | 
			
		||||
            title(VectorLocale.localeToLocalisedString(data.currentLocale).safeCapitalize(data.currentLocale))
 | 
			
		||||
            if (vectorPreferences.developerMode()) {
 | 
			
		||||
            if (host.vectorPreferences.developerMode()) {
 | 
			
		||||
                subtitle(VectorLocale.localeToLocalisedStringInfo(data.currentLocale))
 | 
			
		||||
            }
 | 
			
		||||
            clickListener { listener?.onUseCurrentClicked() }
 | 
			
		||||
            clickListener { host.listener?.onUseCurrentClicked() }
 | 
			
		||||
        }
 | 
			
		||||
        profileSectionItem {
 | 
			
		||||
            id("otherTitle")
 | 
			
		||||
            title(stringProvider.getString(R.string.choose_locale_other_locales_title))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.choose_locale_other_locales_title))
 | 
			
		||||
        }
 | 
			
		||||
        when (list) {
 | 
			
		||||
            is Incomplete -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("loading")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.choose_locale_loading_locales))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.choose_locale_loading_locales))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    ->
 | 
			
		||||
                if (list().isEmpty()) {
 | 
			
		||||
                    noResultItem {
 | 
			
		||||
                        id("noResult")
 | 
			
		||||
                        text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                        text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    list()
 | 
			
		||||
@ -77,10 +78,10 @@ class LocalePickerController @Inject constructor(
 | 
			
		||||
                                localeItem {
 | 
			
		||||
                                    id(it.toString())
 | 
			
		||||
                                    title(VectorLocale.localeToLocalisedString(it).safeCapitalize(it))
 | 
			
		||||
                                    if (vectorPreferences.developerMode()) {
 | 
			
		||||
                                    if (host.vectorPreferences.developerMode()) {
 | 
			
		||||
                                        subtitle(VectorLocale.localeToLocalisedStringInfo(it))
 | 
			
		||||
                                    }
 | 
			
		||||
                                    clickListener { listener?.onLocaleClicked(it) }
 | 
			
		||||
                                    clickListener { host.listener?.onLocaleClicked(it) }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -27,11 +27,12 @@ class PushGateWayController @Inject constructor(
 | 
			
		||||
) : TypedEpoxyController<PushGatewayViewState>() {
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: PushGatewayViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data?.pushGateways?.invoke()?.let { pushers ->
 | 
			
		||||
            if (pushers.isEmpty()) {
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("footer")
 | 
			
		||||
                    text(stringProvider.getString(R.string.settings_push_gateway_no_pushers))
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.settings_push_gateway_no_pushers))
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                pushers.forEach {
 | 
			
		||||
@ -44,7 +45,7 @@ class PushGateWayController @Inject constructor(
 | 
			
		||||
        } ?: run {
 | 
			
		||||
            genericFooterItem {
 | 
			
		||||
                id("loading")
 | 
			
		||||
                text(stringProvider.getString(R.string.loading))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.loading))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ class PushRulesController @Inject constructor(
 | 
			
		||||
) : TypedEpoxyController<PushRulesViewState>() {
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: PushRulesViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        data?.let {
 | 
			
		||||
            it.rules.forEach {
 | 
			
		||||
                pushRuleItem {
 | 
			
		||||
@ -37,7 +38,7 @@ class PushRulesController @Inject constructor(
 | 
			
		||||
        } ?: run {
 | 
			
		||||
            genericFooterItem {
 | 
			
		||||
                id("footer")
 | 
			
		||||
                text(stringProvider.getString(R.string.settings_push_rules_no_rules))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.settings_push_rules_no_rules))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -71,6 +71,7 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: ThreePidsSettingsViewState?) {
 | 
			
		||||
        if (data == null) return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        if (data.uiState is ThreePidsSettingsUiState.Idle) {
 | 
			
		||||
            currentInputValue = ""
 | 
			
		||||
@ -80,7 +81,7 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
            is Loading -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
                    id("loading")
 | 
			
		||||
                    loadingText(stringProvider.getString(R.string.loading))
 | 
			
		||||
                    loadingText(host.stringProvider.getString(R.string.loading))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Fail    -> {
 | 
			
		||||
@ -97,13 +98,14 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildThreePids(list: List<ThreePid>, data: ThreePidsSettingsViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val splited = list.groupBy { it is ThreePid.Email }
 | 
			
		||||
        val emails = splited[true].orEmpty()
 | 
			
		||||
        val msisdn = splited[false].orEmpty()
 | 
			
		||||
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("email")
 | 
			
		||||
            title(stringProvider.getString(R.string.settings_emails))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.settings_emails))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emails.forEach { buildThreePid("email ", it) }
 | 
			
		||||
@ -116,7 +118,7 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
                    if (pendingList.isEmpty() && emails.isEmpty()) {
 | 
			
		||||
                        noResultItem {
 | 
			
		||||
                            id("noEmail")
 | 
			
		||||
                            text(stringProvider.getString(R.string.settings_emails_empty))
 | 
			
		||||
                            text(host.stringProvider.getString(R.string.settings_emails_empty))
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -127,15 +129,15 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
            ThreePidsSettingsUiState.Idle                 ->
 | 
			
		||||
                genericButtonItem {
 | 
			
		||||
                    id("addEmail")
 | 
			
		||||
                    text(stringProvider.getString(R.string.settings_add_email_address))
 | 
			
		||||
                    textColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    buttonClickAction(View.OnClickListener { interactionListener?.addEmail() })
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.settings_add_email_address))
 | 
			
		||||
                    textColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    buttonClickAction(View.OnClickListener { host.interactionListener?.addEmail() })
 | 
			
		||||
                }
 | 
			
		||||
            is ThreePidsSettingsUiState.AddingEmail       -> {
 | 
			
		||||
                settingsEditTextItem {
 | 
			
		||||
                    id("addingEmail")
 | 
			
		||||
                    inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS)
 | 
			
		||||
                    hint(stringProvider.getString(R.string.medium_email))
 | 
			
		||||
                    hint(host.stringProvider.getString(R.string.medium_email))
 | 
			
		||||
                    if (data.editTextReinitiator.isTrue()) {
 | 
			
		||||
                        value("")
 | 
			
		||||
                        requestFocus(true)
 | 
			
		||||
@ -143,18 +145,18 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
                    errorText(data.uiState.error)
 | 
			
		||||
                    interactionListener(object : SettingsEditTextItem.Listener {
 | 
			
		||||
                        override fun onValidate() {
 | 
			
		||||
                            interactionListener?.doAddEmail(currentInputValue)
 | 
			
		||||
                            host.interactionListener?.doAddEmail(host.currentInputValue)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        override fun onTextChange(text: String) {
 | 
			
		||||
                            currentInputValue = text
 | 
			
		||||
                            host.currentInputValue = text
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("contAddingEmail")
 | 
			
		||||
                    continueOnClick { interactionListener?.doAddEmail(currentInputValue) }
 | 
			
		||||
                    cancelOnClick { interactionListener?.cancelAdding() }
 | 
			
		||||
                    continueOnClick { host.interactionListener?.doAddEmail(host.currentInputValue) }
 | 
			
		||||
                    cancelOnClick { host.interactionListener?.cancelAdding() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is ThreePidsSettingsUiState.AddingPhoneNumber -> Unit
 | 
			
		||||
@ -162,7 +164,7 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("msisdn")
 | 
			
		||||
            title(stringProvider.getString(R.string.settings_phone_numbers))
 | 
			
		||||
            title(host.stringProvider.getString(R.string.settings_phone_numbers))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        msisdn.forEach { buildThreePid("msisdn ", it) }
 | 
			
		||||
@ -175,7 +177,7 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
                    if (pendingList.isEmpty() && msisdn.isEmpty()) {
 | 
			
		||||
                        noResultItem {
 | 
			
		||||
                            id("noMsisdn")
 | 
			
		||||
                            text(stringProvider.getString(R.string.settings_phone_number_empty))
 | 
			
		||||
                            text(host.stringProvider.getString(R.string.settings_phone_number_empty))
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -186,20 +188,20 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
            ThreePidsSettingsUiState.Idle                 ->
 | 
			
		||||
                genericButtonItem {
 | 
			
		||||
                    id("addMsisdn")
 | 
			
		||||
                    text(stringProvider.getString(R.string.settings_add_phone_number))
 | 
			
		||||
                    textColor(colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    buttonClickAction(View.OnClickListener { interactionListener?.addMsisdn() })
 | 
			
		||||
                    text(host.stringProvider.getString(R.string.settings_add_phone_number))
 | 
			
		||||
                    textColor(host.colorProvider.getColor(R.color.riotx_accent))
 | 
			
		||||
                    buttonClickAction(View.OnClickListener { host.interactionListener?.addMsisdn() })
 | 
			
		||||
                }
 | 
			
		||||
            is ThreePidsSettingsUiState.AddingEmail       -> Unit
 | 
			
		||||
            is ThreePidsSettingsUiState.AddingPhoneNumber -> {
 | 
			
		||||
                settingsInfoItem {
 | 
			
		||||
                    id("addingMsisdnInfo")
 | 
			
		||||
                    helperText(stringProvider.getString(R.string.login_msisdn_notice))
 | 
			
		||||
                    helperText(host.stringProvider.getString(R.string.login_msisdn_notice))
 | 
			
		||||
                }
 | 
			
		||||
                settingsEditTextItem {
 | 
			
		||||
                    id("addingMsisdn")
 | 
			
		||||
                    inputType(InputType.TYPE_CLASS_PHONE)
 | 
			
		||||
                    hint(stringProvider.getString(R.string.medium_phone_number))
 | 
			
		||||
                    hint(host.stringProvider.getString(R.string.medium_phone_number))
 | 
			
		||||
                    if (data.editTextReinitiator.isTrue()) {
 | 
			
		||||
                        value("")
 | 
			
		||||
                        requestFocus(true)
 | 
			
		||||
@ -207,34 +209,36 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
                    errorText(data.uiState.error)
 | 
			
		||||
                    interactionListener(object : SettingsEditTextItem.Listener {
 | 
			
		||||
                        override fun onValidate() {
 | 
			
		||||
                            interactionListener?.doAddMsisdn(currentInputValue)
 | 
			
		||||
                            host.interactionListener?.doAddMsisdn(host.currentInputValue)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        override fun onTextChange(text: String) {
 | 
			
		||||
                            currentInputValue = text
 | 
			
		||||
                            host.currentInputValue = text
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("contAddingMsisdn")
 | 
			
		||||
                    continueOnClick { interactionListener?.doAddMsisdn(currentInputValue) }
 | 
			
		||||
                    cancelOnClick { interactionListener?.cancelAdding() }
 | 
			
		||||
                    continueOnClick { host.interactionListener?.doAddMsisdn(host.currentInputValue) }
 | 
			
		||||
                    cancelOnClick { host.interactionListener?.cancelAdding() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }.exhaustive
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildThreePid(idPrefix: String, threePid: ThreePid) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        threePidItem {
 | 
			
		||||
            id(idPrefix + threePid.value)
 | 
			
		||||
            // TODO Add an icon for emails
 | 
			
		||||
            // iconResId(if (threePid is ThreePid.Msisdn) R.drawable.ic_phone else null)
 | 
			
		||||
            title(threePid.getFormattedValue())
 | 
			
		||||
            deleteClickListener { interactionListener?.deleteThreePid(threePid) }
 | 
			
		||||
            deleteClickListener { host.interactionListener?.deleteThreePid(threePid) }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildPendingThreePid(data: ThreePidsSettingsViewState, idPrefix: String, threePid: ThreePid) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        threePidItem {
 | 
			
		||||
            id(idPrefix + threePid.value)
 | 
			
		||||
            // TODO Add an icon for emails
 | 
			
		||||
@ -246,43 +250,43 @@ class ThreePidsSettingsController @Inject constructor(
 | 
			
		||||
            is ThreePid.Email  -> {
 | 
			
		||||
                settingsInformationItem {
 | 
			
		||||
                    id("info" + idPrefix + threePid.value)
 | 
			
		||||
                    message(stringProvider.getString(R.string.account_email_validation_message))
 | 
			
		||||
                    colorProvider(colorProvider)
 | 
			
		||||
                    message(host.stringProvider.getString(R.string.account_email_validation_message))
 | 
			
		||||
                    colorProvider(host.colorProvider)
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("cont" + idPrefix + threePid.value)
 | 
			
		||||
                    continueOnClick { interactionListener?.continueThreePid(threePid) }
 | 
			
		||||
                    cancelOnClick { interactionListener?.cancelThreePid(threePid) }
 | 
			
		||||
                    continueOnClick { host.interactionListener?.continueThreePid(threePid) }
 | 
			
		||||
                    cancelOnClick { host.interactionListener?.cancelThreePid(threePid) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is ThreePid.Msisdn -> {
 | 
			
		||||
                settingsInformationItem {
 | 
			
		||||
                    id("info" + idPrefix + threePid.value)
 | 
			
		||||
                    message(stringProvider.getString(R.string.settings_text_message_sent, threePid.getFormattedValue()))
 | 
			
		||||
                    colorProvider(colorProvider)
 | 
			
		||||
                    message(host.stringProvider.getString(R.string.settings_text_message_sent, threePid.getFormattedValue()))
 | 
			
		||||
                    colorProvider(host.colorProvider)
 | 
			
		||||
                }
 | 
			
		||||
                settingsEditTextItem {
 | 
			
		||||
                    id("msisdnVerification${threePid.value}")
 | 
			
		||||
                    inputType(InputType.TYPE_CLASS_NUMBER)
 | 
			
		||||
                    hint(stringProvider.getString(R.string.settings_text_message_sent_hint))
 | 
			
		||||
                    hint(host.stringProvider.getString(R.string.settings_text_message_sent_hint))
 | 
			
		||||
                    if (data.msisdnValidationReinitiator[threePid]?.isTrue() == true) {
 | 
			
		||||
                        value("")
 | 
			
		||||
                    }
 | 
			
		||||
                    errorText(getCodeError(data, threePid))
 | 
			
		||||
                    errorText(host.getCodeError(data, threePid))
 | 
			
		||||
                    interactionListener(object : SettingsEditTextItem.Listener {
 | 
			
		||||
                        override fun onValidate() {
 | 
			
		||||
                            interactionListener?.submitCode(threePid, currentCodes[threePid] ?: "")
 | 
			
		||||
                            host.interactionListener?.submitCode(threePid, host.currentCodes[threePid] ?: "")
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        override fun onTextChange(text: String) {
 | 
			
		||||
                            currentCodes[threePid] = text
 | 
			
		||||
                            host.currentCodes[threePid] = text
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
                settingsContinueCancelItem {
 | 
			
		||||
                    id("cont" + idPrefix + threePid.value)
 | 
			
		||||
                    continueOnClick { interactionListener?.submitCode(threePid, currentCodes[threePid] ?: "") }
 | 
			
		||||
                    cancelOnClick { interactionListener?.cancelThreePid(threePid) }
 | 
			
		||||
                    continueOnClick { host.interactionListener?.submitCode(threePid, host.currentCodes[threePid] ?: "") }
 | 
			
		||||
                    cancelOnClick { host.interactionListener?.cancelThreePid(threePid) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,7 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac
 | 
			
		||||
    var callback: Callback? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: IncomingShareViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (data.sharedData == null || data.filteredRoomSummaries is Incomplete) {
 | 
			
		||||
            loadingItem {
 | 
			
		||||
                id("loading")
 | 
			
		||||
@ -47,7 +48,7 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac
 | 
			
		||||
        if (roomSummaries.isNullOrEmpty()) {
 | 
			
		||||
            noResultItem {
 | 
			
		||||
                id("no_result")
 | 
			
		||||
                text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            roomSummaries.forEach { roomSummary ->
 | 
			
		||||
 | 
			
		||||
@ -65,20 +65,21 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildHeader(state: SoftLogoutViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        loginHeaderItem {
 | 
			
		||||
            id("header")
 | 
			
		||||
        }
 | 
			
		||||
        loginTitleItem {
 | 
			
		||||
            id("title")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_title))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_title))
 | 
			
		||||
        }
 | 
			
		||||
        loginTitleSmallItem {
 | 
			
		||||
            id("signTitle")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_signin_title))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_signin_title))
 | 
			
		||||
        }
 | 
			
		||||
        loginTextItem {
 | 
			
		||||
            id("signText1")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_signin_notice,
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_signin_notice,
 | 
			
		||||
                    state.homeServerUrl.toReducedUrl(),
 | 
			
		||||
                    state.userDisplayName,
 | 
			
		||||
                    state.userId))
 | 
			
		||||
@ -86,12 +87,13 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
        if (state.hasUnsavedKeys) {
 | 
			
		||||
            loginTextItem {
 | 
			
		||||
                id("signText2")
 | 
			
		||||
                text(stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildForm(state: SoftLogoutViewState) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        when (state.asyncHomeServerLoginFlowRequest) {
 | 
			
		||||
            is Incomplete -> {
 | 
			
		||||
                loadingItem {
 | 
			
		||||
@ -101,8 +103,8 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                loginErrorWithRetryItem {
 | 
			
		||||
                    id("errorRetry")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error))
 | 
			
		||||
                    listener { listener?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error))
 | 
			
		||||
                    listener { host.listener?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    -> {
 | 
			
		||||
@ -110,21 +112,21 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
                    LoginMode.Password          -> {
 | 
			
		||||
                        loginPasswordFormItem {
 | 
			
		||||
                            id("passwordForm")
 | 
			
		||||
                            stringProvider(stringProvider)
 | 
			
		||||
                            stringProvider(host.stringProvider)
 | 
			
		||||
                            passwordShown(state.passwordShown)
 | 
			
		||||
                            submitEnabled(state.submitEnabled)
 | 
			
		||||
                            onPasswordEdited { listener?.passwordEdited(it) }
 | 
			
		||||
                            errorText((state.asyncLoginAction as? Fail)?.error?.let { errorFormatter.toHumanReadable(it) })
 | 
			
		||||
                            passwordRevealClickListener { listener?.revealPasswordClicked() }
 | 
			
		||||
                            forgetPasswordClickListener { listener?.forgetPasswordClicked() }
 | 
			
		||||
                            submitClickListener { password -> listener?.signinSubmit(password) }
 | 
			
		||||
                            onPasswordEdited { host.listener?.passwordEdited(it) }
 | 
			
		||||
                            errorText((state.asyncLoginAction as? Fail)?.error?.let { host.errorFormatter.toHumanReadable(it) })
 | 
			
		||||
                            passwordRevealClickListener { host.listener?.revealPasswordClicked() }
 | 
			
		||||
                            forgetPasswordClickListener { host.listener?.forgetPasswordClicked() }
 | 
			
		||||
                            submitClickListener { password -> host.listener?.signinSubmit(password) }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    is LoginMode.Sso            -> {
 | 
			
		||||
                        loginCenterButtonItem {
 | 
			
		||||
                            id("sso")
 | 
			
		||||
                            text(stringProvider.getString(R.string.login_signin_sso))
 | 
			
		||||
                            listener { listener?.signinFallbackSubmit() }
 | 
			
		||||
                            text(host.stringProvider.getString(R.string.login_signin_sso))
 | 
			
		||||
                            listener { host.listener?.signinFallbackSubmit() }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    is LoginMode.SsoAndPassword -> {
 | 
			
		||||
@ -132,8 +134,8 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
                    LoginMode.Unsupported       -> {
 | 
			
		||||
                        loginCenterButtonItem {
 | 
			
		||||
                            id("fallback")
 | 
			
		||||
                            text(stringProvider.getString(R.string.login_signin))
 | 
			
		||||
                            listener { listener?.signinFallbackSubmit() }
 | 
			
		||||
                            text(host.stringProvider.getString(R.string.login_signin))
 | 
			
		||||
                            listener { host.listener?.signinFallbackSubmit() }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    LoginMode.Unknown           -> Unit // Should not happen
 | 
			
		||||
@ -143,18 +145,19 @@ class SoftLogoutController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildClearDataSection() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        loginTitleSmallItem {
 | 
			
		||||
            id("clearDataTitle")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_clear_data_title))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_clear_data_title))
 | 
			
		||||
        }
 | 
			
		||||
        loginTextItem {
 | 
			
		||||
            id("clearDataText")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_clear_data_notice))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_clear_data_notice))
 | 
			
		||||
        }
 | 
			
		||||
        loginRedButtonItem {
 | 
			
		||||
            id("clearDataSubmit")
 | 
			
		||||
            text(stringProvider.getString(R.string.soft_logout_clear_data_submit))
 | 
			
		||||
            listener { listener?.clearData() }
 | 
			
		||||
            text(host.stringProvider.getString(R.string.soft_logout_clear_data_submit))
 | 
			
		||||
            listener { host.listener?.clearData() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -59,6 +59,7 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val nonNullViewState = viewState ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
        buildGroupModels(
 | 
			
		||||
                nonNullViewState.asyncSpaces(),
 | 
			
		||||
                nonNullViewState.selectedGroupingMethod,
 | 
			
		||||
@ -74,30 +75,30 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
            genericItemHeader {
 | 
			
		||||
                id("legacy_groups")
 | 
			
		||||
                text(stringProvider.getString(R.string.groups_header))
 | 
			
		||||
                textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.groups_header))
 | 
			
		||||
                textColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // add home for communities
 | 
			
		||||
            nonNullViewState.myMxItem.invoke()?.let { mxItem ->
 | 
			
		||||
                groupSummaryItem {
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    id("all_communities")
 | 
			
		||||
                    matrixItem(mxItem.copy(displayName = stringProvider.getString(R.string.group_all_communities)))
 | 
			
		||||
                    matrixItem(mxItem.copy(displayName = host.stringProvider.getString(R.string.group_all_communities)))
 | 
			
		||||
                    selected(nonNullViewState.selectedGroupingMethod is RoomGroupingMethod.ByLegacyGroup
 | 
			
		||||
                            && nonNullViewState.selectedGroupingMethod.group() == null)
 | 
			
		||||
                    listener { callback?.onGroupSelected(null) }
 | 
			
		||||
                    listener { host.callback?.onGroupSelected(null) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            nonNullViewState.legacyGroups.forEach { groupSummary ->
 | 
			
		||||
                groupSummaryItem {
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    id(groupSummary.groupId)
 | 
			
		||||
                    matrixItem(groupSummary.toMatrixItem())
 | 
			
		||||
                    selected(nonNullViewState.selectedGroupingMethod is RoomGroupingMethod.ByLegacyGroup
 | 
			
		||||
                            && nonNullViewState.selectedGroupingMethod.group()?.groupId == groupSummary.groupId)
 | 
			
		||||
                    listener { callback?.onGroupSelected(groupSummary) }
 | 
			
		||||
                    listener { host.callback?.onGroupSelected(groupSummary) }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -108,10 +109,11 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
                                 rootSpaces: List<RoomSummary>?,
 | 
			
		||||
                                 expandedStates: Map<String, Boolean>,
 | 
			
		||||
                                 homeCount: RoomAggregateNotificationCount) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        spaceBetaHeaderItem {
 | 
			
		||||
            id("beta_header")
 | 
			
		||||
            clickAction(View.OnClickListener {
 | 
			
		||||
                callback?.sendFeedBack()
 | 
			
		||||
                host.callback?.sendFeedBack()
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -120,13 +122,13 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
        summaries?.filter { it.membership == Membership.INVITE }
 | 
			
		||||
                ?.forEach {
 | 
			
		||||
                    spaceSummaryItem {
 | 
			
		||||
                        avatarRenderer(avatarRenderer)
 | 
			
		||||
                        avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                        id(it.roomId)
 | 
			
		||||
                        matrixItem(it.toMatrixItem())
 | 
			
		||||
                        countState(UnreadCounterBadgeView.State(1, true))
 | 
			
		||||
                        selected(false)
 | 
			
		||||
                        description(stringProvider.getString(R.string.you_are_invited))
 | 
			
		||||
                        listener { callback?.onSpaceInviteSelected(it) }
 | 
			
		||||
                        description(host.stringProvider.getString(R.string.you_are_invited))
 | 
			
		||||
                        listener { host.callback?.onSpaceInviteSelected(it) }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -134,7 +136,7 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
            id("space_home")
 | 
			
		||||
            selected(selected is RoomGroupingMethod.BySpace && selected.space() == null)
 | 
			
		||||
            countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight))
 | 
			
		||||
            listener { callback?.onSpaceSelected(null) }
 | 
			
		||||
            listener { host.callback?.onSpaceSelected(null) }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rootSpaces
 | 
			
		||||
@ -149,15 +151,15 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
                    val expanded = expandedStates[groupSummary.roomId] == true
 | 
			
		||||
 | 
			
		||||
                    spaceSummaryItem {
 | 
			
		||||
                        avatarRenderer(avatarRenderer)
 | 
			
		||||
                        avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                        id(groupSummary.roomId)
 | 
			
		||||
                        hasChildren(hasChildren)
 | 
			
		||||
                        expanded(expanded)
 | 
			
		||||
                        matrixItem(groupSummary.toMatrixItem())
 | 
			
		||||
                        selected(isSelected)
 | 
			
		||||
                        onMore { callback?.onSpaceSettings(groupSummary) }
 | 
			
		||||
                        listener { callback?.onSpaceSelected(groupSummary) }
 | 
			
		||||
                        toggleExpand { callback?.onToggleExpand(groupSummary) }
 | 
			
		||||
                        onMore { host.callback?.onSpaceSettings(groupSummary) }
 | 
			
		||||
                        listener { host.callback?.onSpaceSelected(groupSummary) }
 | 
			
		||||
                        toggleExpand { host.callback?.onToggleExpand(groupSummary) }
 | 
			
		||||
                        countState(
 | 
			
		||||
                                UnreadCounterBadgeView.State(
 | 
			
		||||
                                        groupSummary.notificationCount,
 | 
			
		||||
@ -176,7 +178,7 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
        spaceAddItem {
 | 
			
		||||
            id("create")
 | 
			
		||||
            listener { callback?.onAddSpaceSelected() }
 | 
			
		||||
            listener { host.callback?.onAddSpaceSelected() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -184,6 +186,7 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
                              expandedStates: Map<String, Boolean>,
 | 
			
		||||
                              selected: RoomGroupingMethod,
 | 
			
		||||
                              info: SpaceChildInfo, currentDepth: Int, maxDepth: Int) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (currentDepth >= maxDepth) return
 | 
			
		||||
        val childSummary = summaries?.firstOrNull { it.roomId == info.childRoomId } ?: return
 | 
			
		||||
        // does it have children?
 | 
			
		||||
@ -194,15 +197,15 @@ class SpaceSummaryController @Inject constructor(
 | 
			
		||||
        val isSelected = selected is RoomGroupingMethod.BySpace && childSummary.roomId == selected.space()?.roomId
 | 
			
		||||
 | 
			
		||||
        subSpaceSummaryItem {
 | 
			
		||||
            avatarRenderer(avatarRenderer)
 | 
			
		||||
            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
            id(childSummary.roomId)
 | 
			
		||||
            hasChildren(!subSpaces.isNullOrEmpty())
 | 
			
		||||
            selected(isSelected)
 | 
			
		||||
            expanded(expanded)
 | 
			
		||||
            onMore { callback?.onSpaceSettings(childSummary) }
 | 
			
		||||
            onMore { host.callback?.onSpaceSettings(childSummary) }
 | 
			
		||||
            matrixItem(childSummary.toMatrixItem())
 | 
			
		||||
            listener { callback?.onSpaceSelected(childSummary) }
 | 
			
		||||
            toggleExpand { callback?.onToggleExpand(childSummary) }
 | 
			
		||||
            listener { host.callback?.onSpaceSelected(childSummary) }
 | 
			
		||||
            toggleExpand { host.callback?.onToggleExpand(childSummary) }
 | 
			
		||||
            indent(currentDepth)
 | 
			
		||||
            countState(
 | 
			
		||||
                    UnreadCounterBadgeView.State(
 | 
			
		||||
 | 
			
		||||
@ -36,23 +36,24 @@ class SpaceDefaultRoomEpoxyController @Inject constructor(
 | 
			
		||||
//    var shouldForceFocusOnce = true
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: CreateSpaceState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("info_help_header")
 | 
			
		||||
            style(ItemStyle.TITLE)
 | 
			
		||||
            text(
 | 
			
		||||
                    if (data?.spaceType == SpaceType.Public) {
 | 
			
		||||
                        stringProvider.getString(R.string.create_spaces_room_public_header, data.name)
 | 
			
		||||
                        host.stringProvider.getString(R.string.create_spaces_room_public_header, data.name)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        stringProvider.getString(R.string.create_spaces_room_private_header)
 | 
			
		||||
                        host.stringProvider.getString(R.string.create_spaces_room_private_header)
 | 
			
		||||
                    }
 | 
			
		||||
            )
 | 
			
		||||
            textColor(colorProvider.getColorFromAttribute(R.attr.riot_primary_text_color))
 | 
			
		||||
            textColor(host.colorProvider.getColorFromAttribute(R.attr.riot_primary_text_color))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("info_help")
 | 
			
		||||
            text(
 | 
			
		||||
                    stringProvider.getString(
 | 
			
		||||
                    host.stringProvider.getString(
 | 
			
		||||
                            if (data?.spaceType == SpaceType.Public) {
 | 
			
		||||
                                R.string.create_spaces_room_public_header_desc
 | 
			
		||||
                            } else {
 | 
			
		||||
@ -60,7 +61,7 @@ class SpaceDefaultRoomEpoxyController @Inject constructor(
 | 
			
		||||
                            }
 | 
			
		||||
                    )
 | 
			
		||||
            )
 | 
			
		||||
            textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary))
 | 
			
		||||
            textColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val firstRoomName = data?.defaultRooms?.get(0)
 | 
			
		||||
@ -69,11 +70,11 @@ class SpaceDefaultRoomEpoxyController @Inject constructor(
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(firstRoomName)
 | 
			
		||||
            singleLine(true)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT)
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onNameChange(0, text)
 | 
			
		||||
                host.listener?.onNameChange(0, text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -83,11 +84,11 @@ class SpaceDefaultRoomEpoxyController @Inject constructor(
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(secondRoomName)
 | 
			
		||||
            singleLine(true)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT)
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onNameChange(1, text)
 | 
			
		||||
                host.listener?.onNameChange(1, text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -97,11 +98,11 @@ class SpaceDefaultRoomEpoxyController @Inject constructor(
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(thirdRoomName)
 | 
			
		||||
            singleLine(true)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_section))
 | 
			
		||||
            endIconMode(TextInputLayout.END_ICON_CLEAR_TEXT)
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onNameChange(2, text)
 | 
			
		||||
                host.listener?.onNameChange(2, text)
 | 
			
		||||
            }
 | 
			
		||||
//            onBind { _, view, _ ->
 | 
			
		||||
//                if (shouldForceFocusOnce
 | 
			
		||||
 | 
			
		||||
@ -37,13 +37,14 @@ class SpaceDetailEpoxyController @Inject constructor(
 | 
			
		||||
//    var shouldForceFocusOnce = true
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: CreateSpaceState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        genericFooterItem {
 | 
			
		||||
            id("info_help")
 | 
			
		||||
            text(
 | 
			
		||||
                    if (data?.spaceType == SpaceType.Public) {
 | 
			
		||||
                        stringProvider.getString(R.string.create_spaces_details_public_header)
 | 
			
		||||
                        host.stringProvider.getString(R.string.create_spaces_details_public_header)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        stringProvider.getString(R.string.create_spaces_details_private_header)
 | 
			
		||||
                        host.stringProvider.getString(R.string.create_spaces_details_private_header)
 | 
			
		||||
                    }
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
@ -52,17 +53,17 @@ class SpaceDetailEpoxyController @Inject constructor(
 | 
			
		||||
            id("avatar")
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            imageUri(data?.avatarUri)
 | 
			
		||||
            avatarRenderer(avatarRenderer)
 | 
			
		||||
            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
            matrixItem(data?.name?.let { MatrixItem.RoomItem("!", it, null).takeIf { !it.displayName.isNullOrBlank() } })
 | 
			
		||||
            clickListener { listener?.onAvatarChange() }
 | 
			
		||||
            deleteListener { listener?.onAvatarDelete() }
 | 
			
		||||
            clickListener { host.listener?.onAvatarChange() }
 | 
			
		||||
            deleteListener { host.listener?.onAvatarDelete() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        formEditTextItem {
 | 
			
		||||
            id("name")
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(data?.name)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
            singleLine(true)
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            errorMessage(data?.nameInlineError)
 | 
			
		||||
@ -76,7 +77,7 @@ class SpaceDetailEpoxyController @Inject constructor(
 | 
			
		||||
//                }
 | 
			
		||||
//            }
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onNameChange(text)
 | 
			
		||||
                host.listener?.onNameChange(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -84,11 +85,11 @@ class SpaceDetailEpoxyController @Inject constructor(
 | 
			
		||||
            id("topic")
 | 
			
		||||
            enabled(true)
 | 
			
		||||
            value(data?.topic)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_space_topic_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_space_topic_hint))
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            textSizeSp(16)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                listener?.onTopicChange(text)
 | 
			
		||||
                host.listener?.onTopicChange(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,7 @@ class SpaceDirectoryController @Inject constructor(
 | 
			
		||||
    var listener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: SpaceDirectoryState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val results = data?.spaceSummaryApiResult
 | 
			
		||||
 | 
			
		||||
        if (results is Incomplete) {
 | 
			
		||||
@ -70,13 +71,13 @@ class SpaceDirectoryController @Inject constructor(
 | 
			
		||||
                    tintIcon(false)
 | 
			
		||||
                    text(
 | 
			
		||||
                            span {
 | 
			
		||||
                                span(stringProvider.getString(R.string.spaces_no_server_support_title)) {
 | 
			
		||||
                                span(host.stringProvider.getString(R.string.spaces_no_server_support_title)) {
 | 
			
		||||
                                    textStyle = "bold"
 | 
			
		||||
                                    textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)
 | 
			
		||||
                                    textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)
 | 
			
		||||
                                }
 | 
			
		||||
                                +"\n\n"
 | 
			
		||||
                                span(stringProvider.getString(R.string.spaces_no_server_support_description)) {
 | 
			
		||||
                                    textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                span(host.stringProvider.getString(R.string.spaces_no_server_support_description)) {
 | 
			
		||||
                                    textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                    )
 | 
			
		||||
@ -84,8 +85,8 @@ class SpaceDirectoryController @Inject constructor(
 | 
			
		||||
            } else {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("api_err")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(failure))
 | 
			
		||||
                    listener { listener?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(failure))
 | 
			
		||||
                    listener { host.listener?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -98,7 +99,7 @@ class SpaceDirectoryController @Inject constructor(
 | 
			
		||||
            if (flattenChildInfo.isEmpty()) {
 | 
			
		||||
                genericFooterItem {
 | 
			
		||||
                    id("empty_footer")
 | 
			
		||||
                    stringProvider.getString(R.string.no_result_placeholder)
 | 
			
		||||
                    host.stringProvider.getString(R.string.no_result_placeholder)
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                flattenChildInfo.forEach { info ->
 | 
			
		||||
@ -108,23 +109,23 @@ class SpaceDirectoryController @Inject constructor(
 | 
			
		||||
                    spaceChildInfoItem {
 | 
			
		||||
                        id(info.childRoomId)
 | 
			
		||||
                        matrixItem(MatrixItem.RoomItem(info.childRoomId, info.name, info.avatarUrl))
 | 
			
		||||
                        avatarRenderer(avatarRenderer)
 | 
			
		||||
                        avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                        topic(info.topic)
 | 
			
		||||
                        memberCount(info.activeMemberCount ?: 0)
 | 
			
		||||
                        space(isSpace)
 | 
			
		||||
                        loading(isLoading)
 | 
			
		||||
                        buttonLabel(
 | 
			
		||||
                                if (isJoined) stringProvider.getString(R.string.action_open)
 | 
			
		||||
                                else stringProvider.getString(R.string.join)
 | 
			
		||||
                                if (isJoined) host.stringProvider.getString(R.string.action_open)
 | 
			
		||||
                                else host.stringProvider.getString(R.string.join)
 | 
			
		||||
                        )
 | 
			
		||||
                        apply {
 | 
			
		||||
                            if (isSpace) {
 | 
			
		||||
                                itemClickListener(View.OnClickListener { listener?.onSpaceChildClick(info) })
 | 
			
		||||
                                itemClickListener(View.OnClickListener { host.listener?.onSpaceChildClick(info) })
 | 
			
		||||
                            } else {
 | 
			
		||||
                                itemClickListener(View.OnClickListener { listener?.onRoomClick(info) })
 | 
			
		||||
                                itemClickListener(View.OnClickListener { host.listener?.onRoomClick(info) })
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        buttonClickListener(View.OnClickListener { listener?.onButtonClick(info) })
 | 
			
		||||
                        buttonClickListener(View.OnClickListener { host.listener?.onButtonClick(info) })
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,7 @@ class AddRoomListController @Inject constructor(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun addModels(models: List<EpoxyModel<*>>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val filteredModel = if (ignoreRooms == null) {
 | 
			
		||||
            models
 | 
			
		||||
        } else {
 | 
			
		||||
@ -100,7 +101,7 @@ class AddRoomListController @Inject constructor(
 | 
			
		||||
            add(
 | 
			
		||||
                    RoomCategoryItem_().apply {
 | 
			
		||||
                        id("header")
 | 
			
		||||
                        title(sectionName ?: "")
 | 
			
		||||
                        title(host.sectionName ?: "")
 | 
			
		||||
                        expanded(true)
 | 
			
		||||
                    }
 | 
			
		||||
            )
 | 
			
		||||
@ -108,7 +109,7 @@ class AddRoomListController @Inject constructor(
 | 
			
		||||
                add(
 | 
			
		||||
                        GenericPillItem_().apply {
 | 
			
		||||
                            id("sub_header")
 | 
			
		||||
                            text(subHeaderText)
 | 
			
		||||
                            text(host.subHeaderText)
 | 
			
		||||
                            imageRes(R.drawable.ic_info)
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
@ -123,15 +124,16 @@ class AddRoomListController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> {
 | 
			
		||||
        val host = this
 | 
			
		||||
        if (item == null) return RoomSelectionPlaceHolderItem_().apply { id(currentPosition) }
 | 
			
		||||
        return RoomSelectionItem_().apply {
 | 
			
		||||
            id(item.roomId)
 | 
			
		||||
            matrixItem(item.toMatrixItem())
 | 
			
		||||
            avatarRenderer(this@AddRoomListController.avatarRenderer)
 | 
			
		||||
            space(item.roomType == RoomType.SPACE)
 | 
			
		||||
            selected(selectedItems[item.roomId] ?: false)
 | 
			
		||||
            selected(host.selectedItems[item.roomId] ?: false)
 | 
			
		||||
            itemClickListener(DebouncedClickListener({
 | 
			
		||||
                listener?.onItemSelected(item)
 | 
			
		||||
                host.listener?.onItemSelected(item)
 | 
			
		||||
            }))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,7 @@ class SpaceManageRoomsController @Inject constructor(
 | 
			
		||||
    private val matchFilter = SpaceChildInfoMatchFilter()
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: SpaceManageRoomViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val roomListAsync = data?.childrenInfo
 | 
			
		||||
        if (roomListAsync is Incomplete) {
 | 
			
		||||
            loadingItem { id("loading") }
 | 
			
		||||
@ -51,8 +52,8 @@ class SpaceManageRoomsController @Inject constructor(
 | 
			
		||||
        if (roomListAsync is Fail) {
 | 
			
		||||
            errorWithRetryItem {
 | 
			
		||||
                id("Api Error")
 | 
			
		||||
                text(errorFormatter.toHumanReadable(roomListAsync.error))
 | 
			
		||||
                listener { listener?.retry() }
 | 
			
		||||
                text(host.errorFormatter.toHumanReadable(roomListAsync.error))
 | 
			
		||||
                listener { host.listener?.retry() }
 | 
			
		||||
            }
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
@ -70,12 +71,12 @@ class SpaceManageRoomsController @Inject constructor(
 | 
			
		||||
            roomManageSelectionItem {
 | 
			
		||||
                id(childInfo.childRoomId)
 | 
			
		||||
                matrixItem(childInfo.toMatrixItem())
 | 
			
		||||
                avatarRenderer(avatarRenderer)
 | 
			
		||||
                avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                suggested(childInfo.suggested ?: false)
 | 
			
		||||
                space(childInfo.roomType == RoomType.SPACE)
 | 
			
		||||
                selected(data.selectedRooms.contains(childInfo.childRoomId))
 | 
			
		||||
                itemClickListener(DebouncedClickListener({
 | 
			
		||||
                    listener?.toggleSelection(childInfo)
 | 
			
		||||
                    host.listener?.toggleSelection(childInfo)
 | 
			
		||||
                }))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,7 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomSettingsViewState?) {
 | 
			
		||||
        val roomSummary = data?.roomSummary?.invoke() ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        formEditableSquareAvatarItem {
 | 
			
		||||
            id("avatar")
 | 
			
		||||
@ -68,7 +69,7 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
            when (val avatarAction = data.avatarAction) {
 | 
			
		||||
                RoomSettingsViewState.AvatarAction.None -> {
 | 
			
		||||
                    // Use the current value
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    // We do not want to use the fallback avatar url, which can be the other user avatar, or the current user avatar.
 | 
			
		||||
                    matrixItem(roomSummary.toMatrixItem().copy(avatarUrl = data.currentRoomAvatarUrl))
 | 
			
		||||
                }
 | 
			
		||||
@ -77,8 +78,8 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
                is RoomSettingsViewState.AvatarAction.UpdateAvatar ->
 | 
			
		||||
                    imageUri(avatarAction.newAvatarUri)
 | 
			
		||||
            }
 | 
			
		||||
            clickListener { callback?.onAvatarChange() }
 | 
			
		||||
            deleteListener { callback?.onAvatarDelete() }
 | 
			
		||||
            clickListener { host.callback?.onAvatarChange() }
 | 
			
		||||
            deleteListener { host.callback?.onAvatarDelete() }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        buildProfileSection(
 | 
			
		||||
@ -89,10 +90,10 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
            id("name")
 | 
			
		||||
            enabled(data.actionPermissions.canChangeName)
 | 
			
		||||
            value(data.newName ?: roomSummary.displayName)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_room_name_hint))
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                callback?.onNameChanged(text)
 | 
			
		||||
                host.callback?.onNameChanged(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -100,10 +101,10 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
            id("topic")
 | 
			
		||||
            enabled(data.actionPermissions.canChangeTopic)
 | 
			
		||||
            value(data.newTopic ?: roomSummary.topic)
 | 
			
		||||
            hint(stringProvider.getString(R.string.create_space_topic_hint))
 | 
			
		||||
            hint(host.stringProvider.getString(R.string.create_space_topic_hint))
 | 
			
		||||
            showBottomSeparator(false)
 | 
			
		||||
            onTextChange { text ->
 | 
			
		||||
                callback?.onTopicChanged(text)
 | 
			
		||||
                host.callback?.onTopicChanged(text)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -122,11 +123,11 @@ class SpaceSettingsController @Inject constructor(
 | 
			
		||||
            formSwitchItem {
 | 
			
		||||
                id("isPublic")
 | 
			
		||||
                enabled(data.actionPermissions.canChangeJoinRule)
 | 
			
		||||
                title(stringProvider.getString(R.string.make_this_space_public))
 | 
			
		||||
                title(host.stringProvider.getString(R.string.make_this_space_public))
 | 
			
		||||
                switchChecked(isPublic)
 | 
			
		||||
 | 
			
		||||
                listener { value ->
 | 
			
		||||
                    callback?.setIsPublic(value)
 | 
			
		||||
                    host.callback?.setIsPublic(value)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -58,6 +58,7 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: RoomMemberListViewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val memberSummaries = data?.roomMemberSummaries?.invoke()
 | 
			
		||||
        if (memberSummaries == null) {
 | 
			
		||||
            loadingItem { id("loading") }
 | 
			
		||||
@ -72,7 +73,7 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
            if (filtered.isNotEmpty()) {
 | 
			
		||||
                dividerItem {
 | 
			
		||||
                    id("divider_type_${memberEntry.first.titleRes}")
 | 
			
		||||
                    color(dividerColor)
 | 
			
		||||
                    color(host.dividerColor)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            foundCount += filtered.size
 | 
			
		||||
@ -82,15 +83,15 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
                                profileMatrixItemWithPowerLevel {
 | 
			
		||||
                                    id(roomMember.userId)
 | 
			
		||||
                                    matrixItem(roomMember.toMatrixItem())
 | 
			
		||||
                                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                                    userEncryptionTrustLevel(data.trustLevelMap.invoke()?.get(roomMember.userId))
 | 
			
		||||
                                            .apply {
 | 
			
		||||
                                                val pl = memberEntry.first.toPowerLevelLabel()
 | 
			
		||||
                                                val pl = host.toPowerLevelLabel(memberEntry.first)
 | 
			
		||||
                                                if (memberEntry.first == RoomMemberListCategories.INVITE) {
 | 
			
		||||
                                                    powerLevelLabel(
 | 
			
		||||
                                                            span {
 | 
			
		||||
                                                                span(stringProvider.getString(R.string.invited)) {
 | 
			
		||||
                                                                    textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                                                span(host.stringProvider.getString(R.string.invited)) {
 | 
			
		||||
                                                                    textColor = host.colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary)
 | 
			
		||||
                                                                    textStyle = "bold"
 | 
			
		||||
                                                                    // fontFamily = "monospace"
 | 
			
		||||
                                                                }
 | 
			
		||||
@ -100,10 +101,10 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
                                                    powerLevelLabel(
 | 
			
		||||
                                                            span {
 | 
			
		||||
                                                                span(" $pl ") {
 | 
			
		||||
                                                                    backgroundColor = colorProvider.getColor(R.color.notification_accent_color)
 | 
			
		||||
                                                                    paddingTop = dimensionConverter.dpToPx(2)
 | 
			
		||||
                                                                    paddingBottom = dimensionConverter.dpToPx(2)
 | 
			
		||||
                                                                    textColor = colorProvider.getColor(R.color.white)
 | 
			
		||||
                                                                    backgroundColor = host.colorProvider.getColor(R.color.notification_accent_color)
 | 
			
		||||
                                                                    paddingTop = host.dimensionConverter.dpToPx(2)
 | 
			
		||||
                                                                    paddingBottom = host.dimensionConverter.dpToPx(2)
 | 
			
		||||
                                                                    textColor = host.colorProvider.getColor(R.color.white)
 | 
			
		||||
                                                                    textStyle = "bold"
 | 
			
		||||
                                                                    // fontFamily = "monospace"
 | 
			
		||||
                                                                }
 | 
			
		||||
@ -115,14 +116,14 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
                                            }
 | 
			
		||||
 | 
			
		||||
                                    clickListener { _ ->
 | 
			
		||||
                                        listener?.onSpaceMemberClicked(roomMember)
 | 
			
		||||
                                        host.listener?.onSpaceMemberClicked(roomMember)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            between = { _, roomMemberBefore ->
 | 
			
		||||
                                dividerItem {
 | 
			
		||||
                                    id("divider_${roomMemberBefore.userId}")
 | 
			
		||||
                                    color(dividerColor)
 | 
			
		||||
                                    color(host.dividerColor)
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                    )
 | 
			
		||||
@ -135,30 +136,30 @@ class SpacePeopleListController @Inject constructor(
 | 
			
		||||
                title(
 | 
			
		||||
                        span {
 | 
			
		||||
                            +"\n"
 | 
			
		||||
                            +stringProvider.getString(R.string.no_result_placeholder)
 | 
			
		||||
                            +host.stringProvider.getString(R.string.no_result_placeholder)
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
                description(
 | 
			
		||||
                        span {
 | 
			
		||||
                            +stringProvider.getString(R.string.looking_for_someone_not_in_space, data.roomSummary.invoke()?.displayName ?: "")
 | 
			
		||||
                            +host.stringProvider.getString(R.string.looking_for_someone_not_in_space, data.roomSummary.invoke()?.displayName ?: "")
 | 
			
		||||
                            +"\n"
 | 
			
		||||
                            span("Invite them") {
 | 
			
		||||
                                textColor = colorProvider.getColorFromAttribute(R.attr.colorAccent)
 | 
			
		||||
                                textColor = host.colorProvider.getColorFromAttribute(R.attr.colorAccent)
 | 
			
		||||
                                textStyle = "bold"
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                )
 | 
			
		||||
                itemClickAction(GenericItem.Action("invite").apply {
 | 
			
		||||
                    perform = Runnable {
 | 
			
		||||
                        listener?.onInviteToSpaceSelected()
 | 
			
		||||
                        host.listener?.onInviteToSpaceSelected()
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun RoomMemberListCategories.toPowerLevelLabel(): String? {
 | 
			
		||||
        return when (this) {
 | 
			
		||||
    private fun toPowerLevelLabel(categories: RoomMemberListCategories): String? {
 | 
			
		||||
        return when (categories) {
 | 
			
		||||
            RoomMemberListCategories.ADMIN     -> stringProvider.getString(R.string.power_level_admin)
 | 
			
		||||
            RoomMemberListCategories.MODERATOR -> stringProvider.getString(R.string.power_level_moderator)
 | 
			
		||||
            else                               -> null
 | 
			
		||||
 | 
			
		||||
@ -37,11 +37,12 @@ class SpacePreviewController @Inject constructor(
 | 
			
		||||
    var interactionListener: InteractionListener? = null
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: SpacePreviewState?) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val memberCount = data?.spaceInfo?.invoke()?.memberCount ?: 0
 | 
			
		||||
 | 
			
		||||
        spaceTopSummaryItem {
 | 
			
		||||
            id("info")
 | 
			
		||||
            formattedMemberCount(stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount))
 | 
			
		||||
            formattedMemberCount(host.stringProvider.getQuantityString(R.plurals.room_title_members, memberCount, memberCount))
 | 
			
		||||
            topic(data?.spaceInfo?.invoke()?.topic ?: data?.topic ?: "")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -49,7 +50,7 @@ class SpacePreviewController @Inject constructor(
 | 
			
		||||
        if (result.isNotEmpty()) {
 | 
			
		||||
            genericItemHeader {
 | 
			
		||||
                id("header_rooms")
 | 
			
		||||
                text(stringProvider.getString(R.string.rooms))
 | 
			
		||||
                text(host.stringProvider.getString(R.string.rooms))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            buildChildren(result, 0)
 | 
			
		||||
@ -57,6 +58,7 @@ class SpacePreviewController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildChildren(children: List<ChildInfo>, depth: Int) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        children.forEach { child ->
 | 
			
		||||
 | 
			
		||||
            if (child.isSubSpace == true) {
 | 
			
		||||
@ -66,7 +68,7 @@ class SpacePreviewController @Inject constructor(
 | 
			
		||||
                    title(child.name)
 | 
			
		||||
                    depth(depth)
 | 
			
		||||
                    avatarUrl(child.avatarUrl)
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                }
 | 
			
		||||
                when (child.children) {
 | 
			
		||||
                    is Loading -> {
 | 
			
		||||
@ -87,7 +89,7 @@ class SpacePreviewController @Inject constructor(
 | 
			
		||||
                    topic(child.topic ?: "")
 | 
			
		||||
                    avatarUrl(child.avatarUrl)
 | 
			
		||||
                    memberCount(TextUtils.formatCountToShortDecimal(child.memberCount ?: 0))
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
//            when (child) {
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,7 @@ class TermsController @Inject constructor(
 | 
			
		||||
 | 
			
		||||
    override fun buildModels(data: ReviewTermsViewState?) {
 | 
			
		||||
        data ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        when (data.termsList) {
 | 
			
		||||
            is Incomplete -> {
 | 
			
		||||
@ -46,8 +47,8 @@ class TermsController @Inject constructor(
 | 
			
		||||
            is Fail       -> {
 | 
			
		||||
                errorWithRetryItem {
 | 
			
		||||
                    id("errorRetry")
 | 
			
		||||
                    text(errorFormatter.toHumanReadable(data.termsList.error))
 | 
			
		||||
                    listener { listener?.retry() }
 | 
			
		||||
                    text(host.errorFormatter.toHumanReadable(data.termsList.error))
 | 
			
		||||
                    listener { host.listener?.retry() }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            is Success    -> buildTerms(data.termsList.invoke())
 | 
			
		||||
@ -55,6 +56,7 @@ class TermsController @Inject constructor(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildTerms(termsList: List<Term>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        settingsSectionTitleItem {
 | 
			
		||||
            id("header")
 | 
			
		||||
            titleResId(R.string.widget_integration_review_terms)
 | 
			
		||||
@ -63,12 +65,12 @@ class TermsController @Inject constructor(
 | 
			
		||||
            termItem {
 | 
			
		||||
                id(term.url)
 | 
			
		||||
                name(term.name)
 | 
			
		||||
                description(description)
 | 
			
		||||
                description(host.description)
 | 
			
		||||
                checked(term.accepted)
 | 
			
		||||
 | 
			
		||||
                clickListener(View.OnClickListener { listener?.review(term) })
 | 
			
		||||
                clickListener(View.OnClickListener { host.listener?.review(term) })
 | 
			
		||||
                checkChangeListener { _, isChecked ->
 | 
			
		||||
                    listener?.setChecked(term, isChecked)
 | 
			
		||||
                    host.listener?.setChecked(term, isChecked)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -51,36 +51,37 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
 | 
			
		||||
    override fun buildModels() {
 | 
			
		||||
        val currentState = state ?: return
 | 
			
		||||
        val host = this
 | 
			
		||||
 | 
			
		||||
        // Build generic items
 | 
			
		||||
        if (currentState.searchTerm.isBlank()) {
 | 
			
		||||
            if (currentState.showInviteActions()) {
 | 
			
		||||
                actionItem {
 | 
			
		||||
                    id(R.drawable.ic_share)
 | 
			
		||||
                    title(stringProvider.getString(R.string.invite_friends))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.invite_friends))
 | 
			
		||||
                    actionIconRes(R.drawable.ic_share)
 | 
			
		||||
                    clickAction(View.OnClickListener {
 | 
			
		||||
                        callback?.onInviteFriendClick()
 | 
			
		||||
                        host.callback?.onInviteFriendClick()
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (currentState.showContactBookAction) {
 | 
			
		||||
                actionItem {
 | 
			
		||||
                    id(R.drawable.ic_baseline_perm_contact_calendar_24)
 | 
			
		||||
                    title(stringProvider.getString(R.string.contacts_book_title))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.contacts_book_title))
 | 
			
		||||
                    actionIconRes(R.drawable.ic_baseline_perm_contact_calendar_24)
 | 
			
		||||
                    clickAction(View.OnClickListener {
 | 
			
		||||
                        callback?.onContactBookClick()
 | 
			
		||||
                        host.callback?.onContactBookClick()
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (currentState.showInviteActions()) {
 | 
			
		||||
                actionItem {
 | 
			
		||||
                    id(R.drawable.ic_qr_code_add)
 | 
			
		||||
                    title(stringProvider.getString(R.string.qr_code))
 | 
			
		||||
                    title(host.stringProvider.getString(R.string.qr_code))
 | 
			
		||||
                    actionIconRes(R.drawable.ic_qr_code_add)
 | 
			
		||||
                    clickAction(View.OnClickListener {
 | 
			
		||||
                        callback?.onUseQRCode()
 | 
			
		||||
                        host.callback?.onUseQRCode()
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -109,12 +110,13 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildKnownUsers(currentState: UserListViewState, selectedUsers: List<String>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        currentState.knownUsers()
 | 
			
		||||
                ?.filter { it.userId != session.myUserId }
 | 
			
		||||
                ?.let { userList ->
 | 
			
		||||
                    userListHeaderItem {
 | 
			
		||||
                        id("known_header")
 | 
			
		||||
                        header(stringProvider.getString(R.string.direct_room_user_list_known_title))
 | 
			
		||||
                        header(host.stringProvider.getString(R.string.direct_room_user_list_known_title))
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (userList.isEmpty()) {
 | 
			
		||||
@ -127,9 +129,9 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
                            id(item.userId)
 | 
			
		||||
                            selected(isSelected)
 | 
			
		||||
                            matrixItem(item.toMatrixItem())
 | 
			
		||||
                            avatarRenderer(avatarRenderer)
 | 
			
		||||
                            avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                            clickListener { _ ->
 | 
			
		||||
                                callback?.onItemClick(item)
 | 
			
		||||
                                host.callback?.onItemClick(item)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -137,6 +139,7 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun buildDirectoryUsers(directoryUsers: List<User>, selectedUsers: List<String>, searchTerms: String, ignoreIds: List<String>) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        val toDisplay = directoryUsers
 | 
			
		||||
                .filter { !ignoreIds.contains(it.userId) && it.userId != session.myUserId }
 | 
			
		||||
 | 
			
		||||
@ -145,7 +148,7 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
        }
 | 
			
		||||
        userListHeaderItem {
 | 
			
		||||
            id("suggestions")
 | 
			
		||||
            header(stringProvider.getString(R.string.direct_room_user_list_suggestions_title))
 | 
			
		||||
            header(host.stringProvider.getString(R.string.direct_room_user_list_suggestions_title))
 | 
			
		||||
        }
 | 
			
		||||
        if (toDisplay.isEmpty()) {
 | 
			
		||||
            renderEmptyState()
 | 
			
		||||
@ -156,9 +159,9 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
                    id(user.userId)
 | 
			
		||||
                    selected(isSelected)
 | 
			
		||||
                    matrixItem(user.toMatrixItem())
 | 
			
		||||
                    avatarRenderer(avatarRenderer)
 | 
			
		||||
                    avatarRenderer(host.avatarRenderer)
 | 
			
		||||
                    clickListener { _ ->
 | 
			
		||||
                        callback?.onItemClick(user)
 | 
			
		||||
                        host.callback?.onItemClick(user)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -172,16 +175,18 @@ class UserListController @Inject constructor(private val session: Session,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderEmptyState() {
 | 
			
		||||
        val host = this
 | 
			
		||||
        noResultItem {
 | 
			
		||||
            id("noResult")
 | 
			
		||||
            text(stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
            text(host.stringProvider.getString(R.string.no_result_placeholder))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun renderFailure(failure: Throwable) {
 | 
			
		||||
        val host = this
 | 
			
		||||
        errorWithRetryItem {
 | 
			
		||||
            id("error")
 | 
			
		||||
            text(errorFormatter.toHumanReadable(failure))
 | 
			
		||||
            text(host.errorFormatter.toHumanReadable(failure))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user