Merge branch 'develop' into feature/fga/account_data_rework

This commit is contained in:
ganfra 2021-06-09 18:58:47 +02:00
commit dfcffb9464
686 changed files with 3538 additions and 3646 deletions

View File

@ -37,6 +37,7 @@
<w>threepid</w> <w>threepid</w>
<w>unpublish</w> <w>unpublish</w>
<w>unwedging</w> <w>unwedging</w>
<w>vctr</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

View File

@ -44,6 +44,9 @@ Other changes:
- Add documentation on LoginWizard and RegistrationWizard (#3303) - Add documentation on LoginWizard and RegistrationWizard (#3303)
- Setup towncrier tool (#3293) - Setup towncrier tool (#3293)
Security:
- Element Android shares name of E2EE files with homeserver (#3387)
Changes in Element 1.1.7 (2021-05-12) Changes in Element 1.1.7 (2021-05-12)
=================================================== ===================================================

View File

@ -26,7 +26,7 @@ To install the template (to be done only once):
To create a new screen: To create a new screen:
- First create a new package in your code. - First create a new package in your code.
- Then right click on the package, and select `New/New Vector/RiotX Feature`. - Then right click on the package, and select `New/New Vector/Element Feature`.
- Follow the Wizard, especially replace `Main` by something more relevant to your feature. - Follow the Wizard, especially replace `Main` by something more relevant to your feature.
- Click on `Finish`. - Click on `Finish`.
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :) - Remaining steps are described as TODO in the generated files, or will be pointed out by the compiler, or at runtime :)

View File

@ -55,7 +55,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0' implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.appcompat:appcompat:1.3.0'
implementation "androidx.recyclerview:recyclerview:1.2.0" implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'com.google.android.material:material:1.3.0' implementation 'com.google.android.material:material:1.3.0'
} }

View File

@ -0,0 +1,85 @@
# Color migration
### Changes
- use colors defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=557%3A0
- remove unused resources and code (ex: PercentView)
- split some resource files into smaller file
- rework the theme files
- ensure material theme is used everywhere in the theme and in the layout
- add default style for some views in the theme (ex: Toolbar, etc.)
- add some debug screen in the debug menu, to test the themes and the button style
- rework the button style to use `materialThemeOverlay` attribute
- custom tint icon for menu management has been removed
- comment with `riotx` has been updated
### Main change for developers
- Read migration guide: https://github.com/vector-im/element-android/pull/3459/files#diff-f0e52729d5e4f6eccbcf72246807aa34ed19c4ef5625ca669df998cd1022874b
- Use MaterialAlertDialogBuilder instead of AlertDialog.Builder
- some Epoxy Item included a divider. This has been removed. Use a `dividerItem` or `bottomSheetDividerItem` Epoxy items to add a divider
- RecyclerView.configureWith now take a divider drawable instead of a divider color
### Remaining work
- Cleanup some vector drawables and ensure a tint is always used instead of hard coded color.
### Migration guide
Some colors and color attribute has been removed, here is the list and what has to be used now.
It can help Element Android forks maintainers to migrate their code.
- riotx_text_primary -> ?vctr_content_primary
- riotx_text_secondary -> ?vctr_content_secondary
- riotx_text_tertiary -> ?vctr_content_tertiary
- ?riotx_background -> ?android:colorBackground
- riotx_background_light -> element_background_light
- riotx_background_dark -> element_background_dark
- riotx_background_black -> element_background_black
- riotx_accent -> ?colorPrimary
- riotx_positive_accent -> ?colorPrimary
- riotx_accent_alpha25 -> color_primary_alpha25
- riotx_notice -> ?colorError
- riotx_destructive_accent -> ?colorError
- vector_error_color -> ?colorError
- vector_warning_color -> ?colorError
- riotx_bottom_sheet_background -> ?colorSurface
- riotx_alerter_background -> ?colorSurface
- riotx_username_1 -> element_name_01
- riotx_username_2 -> element_name_02
- riotx_username_3 -> element_name_03
- riotx_username_4 -> element_name_04
- riotx_username_5 -> element_name_05
- riotx_username_6 -> element_name_06
- riotx_username_7 -> element_name_07
- riotx_username_8 -> element_name_08
- riotx_avatar_fill_1 -> element_room_01
- riotx_avatar_fill_2 -> element_room_02
- riotx_avatar_fill_3 -> element_room_03
- white -> @android:color/white
- black -> @android:color/black or emoji_color
- riotx_list_header_background_color -> ?vctr_header_background
- riotx_header_panel_background -> ?vctr_header_background
- riotx_list_bottom_sheet_divider_color -> ?vctr_list_separator_on_surface
- riotx_list_divider_color -> ?vctr_list_separator
- list_divider_color -> ?vctr_list_separator
- riotx_header_panel_border_mobile -> ?vctr_list_separator
- riotx_bottom_nav_background_border_color -> ?vctr_list_separator
- riotx_header_panel_text_secondary -> ?vctr_content_primary
- link_color_light -> element_link_light
- link_color_dark -> element_link_dark
- riotx_toolbar_primary_text_color -> vctr_content_primary
- riotx_toolbar_secondary_text_color -> vctr_content_primary
- riot_primary_text_color -> vctr_content_primary
- riotx_android_secondary -> vctr_content_secondary

View File

@ -42,7 +42,6 @@ import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
import kotlin.jvm.Throws
interface CryptoService { interface CryptoService {
@ -82,9 +81,11 @@ interface CryptoService {
fun getDeviceTrackingStatus(userId: String): Int fun getDeviceTrackingStatus(userId: String): Int
fun importRoomKeys(roomKeysAsArray: ByteArray, password: String, progressListener: ProgressListener?, callback: MatrixCallback<ImportRoomKeysResult>) suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
password: String,
progressListener: ProgressListener?): ImportRoomKeysResult
fun exportRoomKeys(password: String, callback: MatrixCallback<ByteArray>) suspend fun exportRoomKeys(password: String): ByteArray
fun setRoomBlacklistUnverifiedDevices(roomId: String) fun setRoomBlacklistUnverifiedDevices(roomId: String)

View File

@ -35,7 +35,7 @@ interface IdentityService {
/** /**
* Check if the identity server is valid * Check if the identity server is valid
* See https://matrix.org/docs/spec/identity_service/latest#status-check * See https://matrix.org/docs/spec/identity_service/latest#status-check
* RiotX SDK only supports identity server API v2 * Matrix Android SDK2 only supports identity server API v2
*/ */
suspend fun isValidIdentityServer(url: String) suspend fun isValidIdentityServer(url: String)

View File

@ -388,7 +388,7 @@ internal class DefaultCryptoService @Inject constructor(
cryptoStore.close() cryptoStore.close()
} }
// Aways enabled on RiotX // Always enabled on Matrix Android SDK2
override fun isCryptoEnabled() = true override fun isCryptoEnabled() = true
/** /**
@ -928,14 +928,10 @@ internal class DefaultCryptoService @Inject constructor(
* Export the crypto keys * Export the crypto keys
* *
* @param password the password * @param password the password
* @param callback the exported keys * @return the exported keys
*/ */
override fun exportRoomKeys(password: String, callback: MatrixCallback<ByteArray>) { override suspend fun exportRoomKeys(password: String): ByteArray {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { return exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
runCatching {
exportRoomKeys(password, MXMegolmExportEncryption.DEFAULT_ITERATION_COUNT)
}.foldToCallback(callback)
}
} }
/** /**
@ -963,42 +959,37 @@ internal class DefaultCryptoService @Inject constructor(
* @param roomKeysAsArray the room keys as array. * @param roomKeysAsArray the room keys as array.
* @param password the password * @param password the password
* @param progressListener the progress listener * @param progressListener the progress listener
* @param callback the asynchronous callback. * @return the result ImportRoomKeysResult
*/ */
override fun importRoomKeys(roomKeysAsArray: ByteArray, override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
password: String, password: String,
progressListener: ProgressListener?, progressListener: ProgressListener?): ImportRoomKeysResult {
callback: MatrixCallback<ImportRoomKeysResult>) { return withContext(coroutineDispatchers.crypto) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { Timber.v("## CRYPTO | importRoomKeys starts")
runCatching {
withContext(coroutineDispatchers.crypto) {
Timber.v("## CRYPTO | importRoomKeys starts")
val t0 = System.currentTimeMillis() val t0 = System.currentTimeMillis()
val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password) val roomKeys = MXMegolmExportEncryption.decryptMegolmKeyFile(roomKeysAsArray, password)
val t1 = System.currentTimeMillis() val t1 = System.currentTimeMillis()
Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms") Timber.v("## CRYPTO | importRoomKeys : decryptMegolmKeyFile done in ${t1 - t0} ms")
val importedSessions = MoshiProvider.providesMoshi() val importedSessions = MoshiProvider.providesMoshi()
.adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java)) .adapter<List<MegolmSessionData>>(Types.newParameterizedType(List::class.java, MegolmSessionData::class.java))
.fromJson(roomKeys) .fromJson(roomKeys)
val t2 = System.currentTimeMillis() val t2 = System.currentTimeMillis()
Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms") Timber.v("## CRYPTO | importRoomKeys : JSON parsing ${t2 - t1} ms")
if (importedSessions == null) { if (importedSessions == null) {
throw Exception("Error") throw Exception("Error")
} }
megolmSessionDataImporter.handle( megolmSessionDataImporter.handle(
megolmSessionsData = importedSessions, megolmSessionsData = importedSessions,
fromBackup = false, fromBackup = false,
progressListener = progressListener progressListener = progressListener
) )
}
}.foldToCallback(callback)
} }
} }

View File

@ -155,7 +155,7 @@ internal class MXMegolmDecryption(private val userId: String,
withHeldInfo.code?.value ?: "", withHeldInfo.code?.value ?: "",
withHeldInfo.reason) withHeldInfo.reason)
} else { } else {
// This is un-used in riotX SDK, not sure if needed // This is un-used in Matrix Android SDK2, not sure if needed
// addEventToPendingList(event, timeline) // addEventToPendingList(event, timeline)
if (requestKeysOnFail) { if (requestKeysOnFail) {
requestKeysForEvent(event, false) requestKeysForEvent(event, false)

View File

@ -153,7 +153,7 @@ internal class DefaultLegacySessionImporter @Inject constructor(
} }
private fun importCryptoDb(legacyConfig: LegacyHomeServerConnectionConfig) { private fun importCryptoDb(legacyConfig: LegacyHomeServerConnectionConfig) {
// Here we migrate the DB, we copy the crypto DB to the location specific to RiotX, and we encrypt it. // Here we migrate the DB, we copy the crypto DB to the location specific to Matrix SDK2, and we encrypt it.
val userMd5 = legacyConfig.credentials.userId.md5() val userMd5 = legacyConfig.credentials.userId.md5()
val sessionId = legacyConfig.credentials.let { (if (it.deviceId.isNullOrBlank()) it.userId else "${it.userId}|${it.deviceId}").md5() } val sessionId = legacyConfig.credentials.let { (if (it.deviceId.isNullOrBlank()) it.userId else "${it.userId}|${it.deviceId}").md5() }
@ -177,12 +177,12 @@ internal class DefaultLegacySessionImporter @Inject constructor(
Timber.d("Migration: copy DB to encrypted DB") Timber.d("Migration: copy DB to encrypted DB")
Realm.getInstance(realmConfiguration).use { Realm.getInstance(realmConfiguration).use {
// Move the DB to the new location, handled by RiotX // Move the DB to the new location, handled by Matrix SDK2
it.writeEncryptedCopyTo(File(newLocation, realmConfiguration.realmFileName), realmKeysUtils.getRealmEncryptionKey(keyAlias)) it.writeEncryptedCopyTo(File(newLocation, realmConfiguration.realmFileName), realmKeysUtils.getRealmEncryptionKey(keyAlias))
} }
} }
// Delete all the files created by Riot Android which will not be used anymore by RiotX // Delete all the files created by Riot Android which will not be used anymore by Element
private fun clearFileSystem(legacyConfig: LegacyHomeServerConnectionConfig) { private fun clearFileSystem(legacyConfig: LegacyHomeServerConnectionConfig) {
val cryptoFolder = legacyConfig.credentials.userId.md5() val cryptoFolder = legacyConfig.credentials.userId.md5()

View File

@ -36,7 +36,7 @@ internal class UserAgentHolder @Inject constructor(private val context: Context,
/** /**
* Create an user agent with the application version. * Create an user agent with the application version.
* Ex: RiotX/1.0.0 (Linux; U; Android 6.0.1; SM-A510F Build/MMB29; Flavour GPlay; MatrixAndroidSDK_X 1.0) * Ex: Element/1.0.0 (Linux; U; Android 6.0.1; SM-A510F Build/MMB29; Flavour GPlay; MatrixAndroidSDK_X 1.0)
* *
* @param flavorDescription the flavor description * @param flavorDescription the flavor description
*/ */

View File

@ -24,7 +24,6 @@ import io.realm.RealmQuery
import io.realm.RealmResults import io.realm.RealmResults
import io.realm.Sort import io.realm.Sort
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
@ -168,9 +167,7 @@ internal class DefaultTimeline(
timelineEvents.addChangeListener(eventsChangeListener) timelineEvents.addChangeListener(eventsChangeListener)
handleInitialLoad() handleInitialLoad()
loadRoomMembersTask loadRoomMembersTask
.configureWith(LoadRoomMembersTask.Params(roomId)) { .configureWith(LoadRoomMembersTask.Params(roomId))
this.callback = NoOpMatrixCallback()
}
.executeBy(taskExecutor) .executeBy(taskExecutor)
// Ensure ReadReceipt from init sync are loaded // Ensure ReadReceipt from init sync are loaded

View File

@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.session.room.typing
import android.os.SystemClock import android.os.SystemClock
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import org.matrix.android.sdk.api.MatrixCallback import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.room.typing.TypingService import org.matrix.android.sdk.api.session.room.typing.TypingService
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.configureWith
import timber.log.Timber import timber.log.Timber
/** /**
@ -35,7 +35,6 @@ import timber.log.Timber
*/ */
internal class DefaultTypingService @AssistedInject constructor( internal class DefaultTypingService @AssistedInject constructor(
@Assisted private val roomId: String, @Assisted private val roomId: String,
private val taskExecutor: TaskExecutor,
private val sendTypingTask: SendTypingTask private val sendTypingTask: SendTypingTask
) : TypingService { ) : TypingService {
@ -44,8 +43,8 @@ internal class DefaultTypingService @AssistedInject constructor(
fun create(roomId: String): DefaultTypingService fun create(roomId: String): DefaultTypingService
} }
private var currentTask: Cancelable? = null private val coroutineScope = CoroutineScope(Job())
private var currentAutoStopTask: Cancelable? = null private var currentTask: Job? = null
// What the homeserver knows // What the homeserver knows
private var userIsTyping = false private var userIsTyping = false
@ -53,26 +52,24 @@ internal class DefaultTypingService @AssistedInject constructor(
// Last time the user is typing event has been sent // Last time the user is typing event has been sent
private var lastRequestTimestamp: Long = 0 private var lastRequestTimestamp: Long = 0
/**
* Notify to the server that the user is typing and schedule the auto typing off
*/
override fun userIsTyping() { override fun userIsTyping() {
scheduleAutoStop()
val now = SystemClock.elapsedRealtime() val now = SystemClock.elapsedRealtime()
if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
Timber.d("Typing: Skip start request")
return
}
Timber.d("Typing: Send start request")
userIsTyping = true
lastRequestTimestamp = now
currentTask?.cancel() currentTask?.cancel()
currentTask = coroutineScope.launch {
val params = SendTypingTask.Params(roomId, true) if (userIsTyping && now < lastRequestTimestamp + MIN_DELAY_BETWEEN_TWO_USER_IS_TYPING_REQUESTS_MILLIS) {
currentTask = sendTypingTask Timber.d("Typing: Skip start request")
.configureWith(params) } else {
.executeBy(taskExecutor) Timber.d("Typing: Send start request")
lastRequestTimestamp = now
sendRequest(true)
}
delay(MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS)
Timber.d("Typing: auto stop")
sendRequest(false)
}
} }
override fun userStopsTyping() { override fun userStopsTyping() {
@ -82,35 +79,22 @@ internal class DefaultTypingService @AssistedInject constructor(
} }
Timber.d("Typing: Send stop request") Timber.d("Typing: Send stop request")
userIsTyping = false
lastRequestTimestamp = 0 lastRequestTimestamp = 0
currentAutoStopTask?.cancel()
currentTask?.cancel() currentTask?.cancel()
currentTask = coroutineScope.launch {
val params = SendTypingTask.Params(roomId, false) sendRequest(false)
currentTask = sendTypingTask }
.configureWith(params)
.executeBy(taskExecutor)
} }
private fun scheduleAutoStop() { private suspend fun sendRequest(isTyping: Boolean) {
Timber.d("Typing: Schedule auto stop") try {
currentAutoStopTask?.cancel() sendTypingTask.execute(SendTypingTask.Params(roomId, isTyping))
userIsTyping = isTyping
val params = SendTypingTask.Params( } catch (failure: Throwable) {
roomId, // Ignore network error, etc...
false, Timber.w(failure, "Unable to send typing request")
delay = MIN_DELAY_TO_SEND_STOP_TYPING_REQUEST_WHEN_NO_USER_ACTIVITY_MILLIS) }
currentAutoStopTask = sendTypingTask
.configureWith(params) {
callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
userIsTyping = false
}
}
}
.executeBy(taskExecutor)
} }
companion object { companion object {

View File

@ -17,11 +17,10 @@
package org.matrix.android.sdk.internal.session.room.typing package org.matrix.android.sdk.internal.session.room.typing
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.task.Task
import kotlinx.coroutines.delay
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import javax.inject.Inject import javax.inject.Inject
internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> { internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
@ -29,9 +28,7 @@ internal interface SendTypingTask : Task<SendTypingTask.Params, Unit> {
data class Params( data class Params(
val roomId: String, val roomId: String,
val isTyping: Boolean, val isTyping: Boolean,
val typingTimeoutMillis: Int? = 30_000, val typingTimeoutMillis: Int? = 30_000
// Optional delay before sending the request to the homeserver
val delay: Long? = null
) )
} }
@ -42,8 +39,6 @@ internal class DefaultSendTypingTask @Inject constructor(
) : SendTypingTask { ) : SendTypingTask {
override suspend fun execute(params: SendTypingTask.Params) { override suspend fun execute(params: SendTypingTask.Params) {
delay(params.delay ?: -1)
executeRequest(globalErrorReceiver) { executeRequest(globalErrorReceiver) {
roomAPI.sendTypingState( roomAPI.sendTypingState(
params.roomId, params.roomId,

View File

@ -0,0 +1 @@
Migrate DefaultTypingService, KeysImporter and KeysExporter to coroutines

View File

@ -0,0 +1 @@
Update Message Composer design

View File

@ -0,0 +1,2 @@
Migrate to new colors and cleanup the style and theme
Ref: https://material.io/blog/migrate-android-material-components

View File

@ -136,8 +136,9 @@ android\.R\.id\.home===2
### Kotlin conversion tools introduce this, but is can be replace by trim() ### Kotlin conversion tools introduce this, but is can be replace by trim()
trim \{ it \<\= \' \' \} trim \{ it \<\= \' \' \}
### Use AlertDialog form v7 compat lib ### Use MaterialAlertDialogBuilder
android\.app\.AlertDialog android\.app\.AlertDialog
androidx\.appcompat\.app\.AlertDialog===4
### Put the operator at the beginning of next line ### Put the operator at the beginning of next line
&&$ &&$

View File

@ -84,3 +84,22 @@ layout_constraintLeft_
### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to ### Use androidx.recyclerview.widget.RecyclerView because EpoxyRecyclerViews add behavior we do not want to
<com\.airbnb\.epoxy\.EpoxyRecyclerView <com\.airbnb\.epoxy\.EpoxyRecyclerView
### Use Button instead of MaterialButton, the inflater will automatically inflate MaterialButton.
<com\.google\.android\.material\.button\.MaterialButton
<androidx\.appcompat\.widget\.AppCompatButton
### Use CheckBox instead of MaterialCheckBox, the inflater will automatically inflate MaterialCheckBox.
<com\.google\.android\.material\.checkbox\.MaterialCheckBox
### Use RadioButton instead of MaterialRadioButton, the inflater will automatically inflate Material Views.
<com\.google\.android\.material\.radiobutton\.MaterialRadioButton
### Use com.google.android.material.switchmaterial.SwitchMaterial instead of Switch, the inflater will not automatically inflate Material Views for Switch.
<Switch
### Use colorSecondary
colorAccent
### Use MaterialCardView
<androidx\.cardview\.widget\.CardView

View File

@ -326,7 +326,7 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "androidx.recyclerview:recyclerview:1.2.0" implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.appcompat:appcompat:1.3.0'
implementation "androidx.fragment:fragment-ktx:$fragment_version" implementation "androidx.fragment:fragment-ktx:$fragment_version"
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

View File

@ -6,11 +6,26 @@
<activity android:name=".features.debug.TestLinkifyActivity" /> <activity android:name=".features.debug.TestLinkifyActivity" />
<activity android:name=".features.debug.sas.DebugSasEmojiActivity" /> <activity android:name=".features.debug.sas.DebugSasEmojiActivity" />
<activity <activity
android:name=".features.debug.DebugMaterialThemeLightActivity" android:name=".features.debug.DebugMaterialThemeLightDefaultActivity"
android:theme="@style/VectorMaterialThemeDebugLight" /> android:theme="@style/VectorMaterialThemeDebugLight" />
<activity <activity
android:name=".features.debug.DebugMaterialThemeDarkActivity" android:name=".features.debug.DebugMaterialThemeLightTestActivity"
android:theme="@style/VectorMaterialThemeDebugLight.Test" />
<activity
android:name=".features.debug.DebugMaterialThemeLightVectorActivity"
android:theme="@style/AppTheme.Light" />
<activity
android:name=".features.debug.DebugMaterialThemeDarkDefaultActivity"
android:theme="@style/VectorMaterialThemeDebugDark" /> android:theme="@style/VectorMaterialThemeDebugDark" />
<activity
android:name=".features.debug.DebugMaterialThemeDarkTestActivity"
android:theme="@style/VectorMaterialThemeDebugDark.Test" />
<activity
android:name=".features.debug.DebugMaterialThemeDarkVectorActivity"
android:theme="@style/AppTheme.Dark" />
<activity
android:name=".features.debug.DebugVectorButtonStylesActivity"
android:theme="@style/AppTheme.Light" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import im.vector.app.databinding.ActivityTestMaterialThemeBinding
class DebugBottomSheet : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// Reuse tha Activity layout
val binding = ActivityTestMaterialThemeBinding.inflate(inflater, container, false)
return binding.root
}
}

View File

@ -18,9 +18,8 @@ package im.vector.app.features.debug
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
@ -45,7 +44,8 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
} }
views.debugShowDialog.setOnClickListener { views.debugShowDialog.setOnClickListener {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle("Dialog title")
.setMessage("Dialog content") .setMessage("Dialog content")
.setIcon(R.drawable.ic_settings_x) .setIcon(R.drawable.ic_settings_x)
.setPositiveButton("Positive", null) .setPositiveButton("Positive", null)
@ -55,7 +55,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
} }
views.debugShowBottomSheet.setOnClickListener { views.debugShowBottomSheet.setOnClickListener {
BottomSheetDialogFragment().show(supportFragmentManager, "TAG") DebugBottomSheet().show(supportFragmentManager, "TAG")
} }
} }

View File

@ -0,0 +1,19 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
class DebugMaterialThemeDarkDefaultActivity : DebugMaterialThemeActivity()

View File

@ -16,4 +16,4 @@
package im.vector.app.features.debug package im.vector.app.features.debug
class DebugMaterialThemeDarkActivity : DebugMaterialThemeActivity() class DebugMaterialThemeDarkTestActivity : DebugMaterialThemeActivity()

View File

@ -0,0 +1,19 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
class DebugMaterialThemeDarkVectorActivity : DebugMaterialThemeActivity()

View File

@ -0,0 +1,19 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
class DebugMaterialThemeLightDefaultActivity : DebugMaterialThemeActivity()

View File

@ -16,4 +16,4 @@
package im.vector.app.features.debug package im.vector.app.features.debug
class DebugMaterialThemeLightActivity : DebugMaterialThemeActivity() class DebugMaterialThemeLightTestActivity : DebugMaterialThemeActivity()

View File

@ -0,0 +1,19 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
class DebugMaterialThemeLightVectorActivity : DebugMaterialThemeActivity()

View File

@ -71,10 +71,29 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
private fun setupViews() { private fun setupViews() {
views.debugTestTextViewLink.setOnClickListener { testTextViewLink() } views.debugTestTextViewLink.setOnClickListener { testTextViewLink() }
views.debugOpenButtonStyles.setOnClickListener {
startActivity(Intent(this, DebugVectorButtonStylesActivity::class.java))
}
views.debugShowSasEmoji.setOnClickListener { showSasEmoji() } views.debugShowSasEmoji.setOnClickListener { showSasEmoji() }
views.debugTestNotification.setOnClickListener { testNotification() } views.debugTestNotification.setOnClickListener { testNotification() }
views.debugTestMaterialThemeLight.setOnClickListener { testMaterialThemeLight() } views.debugTestMaterialThemeLightDefault.setOnClickListener {
views.debugTestMaterialThemeDark.setOnClickListener { testMaterialThemeDark() } startActivity(Intent(this, DebugMaterialThemeLightDefaultActivity::class.java))
}
views.debugTestMaterialThemeLightTest.setOnClickListener {
startActivity(Intent(this, DebugMaterialThemeLightTestActivity::class.java))
}
views.debugTestMaterialThemeLightVector.setOnClickListener {
startActivity(Intent(this, DebugMaterialThemeLightVectorActivity::class.java))
}
views.debugTestMaterialThemeDarkDefault.setOnClickListener {
startActivity(Intent(this, DebugMaterialThemeDarkDefaultActivity::class.java))
}
views.debugTestMaterialThemeDarkTest.setOnClickListener {
startActivity(Intent(this, DebugMaterialThemeDarkTestActivity::class.java))
}
views.debugTestMaterialThemeDarkVector.setOnClickListener {
startActivity(Intent(this, DebugMaterialThemeDarkVectorActivity::class.java))
}
views.debugTestCrash.setOnClickListener { testCrash() } views.debugTestCrash.setOnClickListener { testCrash() }
views.debugScanQrCode.setOnClickListener { scanQRCode() } views.debugScanQrCode.setOnClickListener { scanQRCode() }
} }
@ -174,14 +193,6 @@ class DebugMenuActivity : VectorBaseActivity<ActivityDebugMenuBinding>() {
) )
} }
private fun testMaterialThemeLight() {
startActivity(Intent(this, DebugMaterialThemeLightActivity::class.java))
}
private fun testMaterialThemeDark() {
startActivity(Intent(this, DebugMaterialThemeDarkActivity::class.java))
}
private fun testCrash() { private fun testCrash() {
throw RuntimeException("Application crashed from user demand") throw RuntimeException("Application crashed from user demand")
} }

View File

@ -0,0 +1,24 @@
/*
* Copyright 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.debug
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityDebugButtonStylesBinding
class DebugVectorButtonStylesActivity : VectorBaseActivity<ActivityDebugButtonStylesBinding>() {
override fun getBinding() = ActivityDebugButtonStylesBinding.inflate(layoutInflater)
}

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".features.debug.DebugVectorButtonStylesActivity"
tools:ignore="HardcodedText">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<Button
style="@style/VectorButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Default" />
<Button
style="@style/VectorButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Default disabled" />
<Button
style="@style/VectorButtonStyleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text" />
<Button
style="@style/VectorButtonStyleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Text disabled" />
<Button
style="@style/VectorButtonStyle.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Positive" />
<Button
style="@style/VectorButtonStyle.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Positive disabled" />
<Button
style="@style/VectorButtonStyle.Destructive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Destructive" />
<Button
style="@style/VectorButtonStyle.Destructive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Destructive disabled" />
<Button
style="@style/VectorButtonStyleUnelevated.Bot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bot" />
<Button
style="@style/VectorButtonStyleUnelevated.Bot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Bot disabled" />
<Button
style="@style/VectorButtonStyleOutlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Outline" />
<Button
style="@style/VectorButtonStyleOutlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Outline disabled" />
<Button
style="@style/VectorButtonStyleOutlined.Poll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Poll " />
<Button
style="@style/VectorButtonStyleOutlined.Poll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Poll disabled" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/palette_azure"
android:orientation="vertical"
android:padding="8dp">
<Button
style="@style/AlerterButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Alerter" />
<Button
style="@style/AlerterButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Alerter disabled" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -20,51 +20,106 @@
android:padding="@dimen/layout_horizontal_margin" android:padding="@dimen/layout_horizontal_margin"
android:showDividers="middle"> android:showDividers="middle">
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debug_test_text_view_link" android:id="@+id/debug_test_text_view_link"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Test linkification" /> android:text="Test linkification" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debug_test_notification" android:id="@+id/debug_test_notification"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Test Notification" /> android:text="Test Notification" />
<com.google.android.material.button.MaterialButton <TextView
android:id="@+id/debug_test_material_theme_light"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Test Material theme Light" /> android:text="Light theme" />
<com.google.android.material.button.MaterialButton <LinearLayout
android:id="@+id/debug_test_material_theme_dark" android:layout_width="match_parent"
style="@style/VectorButtonStyle" android:layout_height="wrap_content">
<Button
android:id="@+id/debug_test_material_theme_light_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Default" />
<Button
android:id="@+id/debug_test_material_theme_light_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Test" />
<Button
android:id="@+id/debug_test_material_theme_light_vector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Vector" />
</LinearLayout>
<TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Test Material theme Dark" /> android:text="Dark theme" />
<com.google.android.material.button.MaterialButton <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/debug_test_material_theme_dark_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Default" />
<Button
android:id="@+id/debug_test_material_theme_dark_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Test" />
<Button
android:id="@+id/debug_test_material_theme_dark_vector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="Vector" />
</LinearLayout>
<Button
android:id="@+id/debug_open_button_styles"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="See button styles" />
<Button
android:id="@+id/debug_show_sas_emoji" android:id="@+id/debug_show_sas_emoji"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Display all SAS emoji" /> android:text="Display all SAS emoji" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debug_test_crash" android:id="@+id/debug_test_crash"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Crash the app" /> android:text="Crash the app" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debug_scan_qr_code" android:id="@+id/debug_scan_qr_code"
style="@style/VectorButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Scan QR-code" /> android:text="Scan QR-code" />

View File

@ -5,7 +5,6 @@
android:id="@+id/coordinatorLayout" android:id="@+id/coordinatorLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".features.debug.DebugMaterialThemeActivity" tools:context=".features.debug.DebugMaterialThemeActivity"
tools:ignore="HardcodedText"> tools:ignore="HardcodedText">
@ -28,6 +27,229 @@
app:subtitle="Toolbar Subtitle" app:subtitle="Toolbar Subtitle"
app:title="Toolbar Title" /> app:title="Toolbar Title" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:divider="@drawable/linear_divider"
android:showDividers="middle">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#FFFFFF"
android:divider="@drawable/linear_divider"
android:orientation="vertical"
android:padding="8dp"
android:showDividers="middle">
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorPrimary"
android:text="colorPrimary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorPrimaryVariant"
android:text="colorPrimaryVariant" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorOnPrimary"
android:text="colorOnPrimary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorSecondary"
android:text="colorSecondary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorSecondaryVariant"
android:text="colorSecondaryVariant" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorOnSecondary"
android:text="colorOnSecondary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorError"
android:text="colorError" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorOnError"
android:text="colorOnError" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorSurface"
android:text="colorSurface" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorOnSurface"
android:text="colorOnSurface" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:colorBackground"
android:text="android:colorBackground" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorOnBackground"
android:text="colorOnBackground" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?colorAccent"
android:text="colorAccent" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:statusBarColor"
android:text="android:statusBarColor" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:navigationBarColor"
android:text="android:navigationBarColor" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:textColorPrimary"
android:text="android:textColorPrimary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:textColorSecondary"
android:text="android:textColorSecondary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:textColorTertiary"
android:text="android:textColorTertiary" />
<TextView
style="@style/DebugTextColorDemo.White"
android:background="?android:textColorLink"
android:text="android:textColorLink" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#000000"
android:divider="@drawable/linear_divider"
android:dividerPadding="8dp"
android:orientation="vertical"
android:padding="8dp"
android:showDividers="middle">
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorPrimary"
android:text="colorPrimary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorPrimaryVariant"
android:text="colorPrimaryVariant" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorOnPrimary"
android:text="colorOnPrimary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorSecondary"
android:text="colorSecondary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorSecondaryVariant"
android:text="colorSecondaryVariant" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorOnSecondary"
android:text="colorOnSecondary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorError"
android:text="colorError" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorOnError"
android:text="colorOnError" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorSurface"
android:text="colorSurface" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorOnSurface"
android:text="colorOnSurface" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:colorBackground"
android:text="android:colorBackground" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorOnBackground"
android:text="colorOnBackground" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?colorAccent"
android:text="colorAccent" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:statusBarColor"
android:text="android:statusBarColor" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:navigationBarColor"
android:text="android:navigationBarColor" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:textColorPrimary"
android:text="android:textColorPrimary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:textColorSecondary"
android:text="android:textColorSecondary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:textColorTertiary"
android:text="android:textColorTertiary" />
<TextView
style="@style/DebugTextColorDemo.Black"
android:background="?android:textColorLink"
android:text="android:textColorLink" />
</LinearLayout>
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -81,60 +303,105 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buttons" />
<com.google.android.material.button.MaterialButton <Button
style="@style/Widget.MaterialComponents.Button" style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Material Button Classic" android:text="Classic"
app:icon="@drawable/ic_settings_x" /> app:icon="@drawable/ic_settings_x" />
<com.google.android.material.button.MaterialButton <Button
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Classic Disabled"
app:icon="@drawable/ic_settings_x" />
<Button
style="@style/Widget.MaterialComponents.Button.OutlinedButton" style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Material Button OutlinedButton" android:text="OutlinedButton"
app:icon="@drawable/ic_settings_x" /> app:icon="@drawable/ic_settings_x" />
<com.google.android.material.button.MaterialButton <Button
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="OutlinedButton Disabled"
app:icon="@drawable/ic_settings_x" />
<Button
style="@style/Widget.MaterialComponents.Button.TextButton" style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Material Button TextButton" android:text="TextButton"
app:icon="@drawable/ic_settings_x" /> app:icon="@drawable/ic_settings_x" />
<com.google.android.material.button.MaterialButton <Button
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="TextButton Disabled"
app:icon="@drawable/ic_settings_x" />
<Button
style="@style/Widget.MaterialComponents.Button.UnelevatedButton" style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Material Button UnelevatedButton" android:text="UnelevatedButton"
app:icon="@drawable/ic_settings_x" /> app:icon="@drawable/ic_settings_x" />
<com.google.android.material.button.MaterialButton <Button
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="UnelevatedButton Disabled"
app:icon="@drawable/ic_settings_x" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Actions" />
<Button
android:id="@+id/debugShowSnackbar" android:id="@+id/debugShowSnackbar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Show Snackbar" /> android:text="Show Snackbar" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debugShowToast" android:id="@+id/debugShowToast"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Show Toast" /> android:text="Show Toast" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debugShowDialog" android:id="@+id/debugShowDialog"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Show Dialog" /> android:text="Show Dialog" />
<com.google.android.material.button.MaterialButton <Button
android:id="@+id/debugShowBottomSheet" android:id="@+id/debugShowBottomSheet"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Show Bottom Sheet" /> android:text="Show Bottom Sheet" />
<com.google.android.material.checkbox.MaterialCheckBox <CheckBox
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Material CheckBox" /> android:text="Material CheckBox" />
@ -146,7 +413,8 @@
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -159,9 +427,16 @@
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_margin="16dp"
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:src="@drawable/ic_settings_x" /> android:src="@drawable/ic_settings_x" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/home_bottom_navigation" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@ -8,8 +8,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:textColor="@color/black" android:textColor="@color/emoji_color"
android:textSize="22sp" android:textSize="22sp"
tools:text="🔧" /> tools:text="🔧" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -38,4 +38,4 @@
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>

View File

@ -7,6 +7,10 @@
<style name="VectorMaterialThemeDebugLight" parent="Theme.MaterialComponents.Light.NoActionBar"> <style name="VectorMaterialThemeDebugLight" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Keep all default value -->
</style>
<style name="VectorMaterialThemeDebugLight.Test">
<item name="colorPrimary">#7F7F00</item> <item name="colorPrimary">#7F7F00</item>
<item name="colorPrimaryVariant">#00FF00</item> <item name="colorPrimaryVariant">#00FF00</item>
<item name="colorOnPrimary">#0000FF</item> <item name="colorOnPrimary">#0000FF</item>
@ -24,14 +28,17 @@
<item name="android:colorBackground">#FF7777</item> <item name="android:colorBackground">#FF7777</item>
<item name="colorOnBackground">#077700</item> <item name="colorOnBackground">#077700</item>
<!-- TODO is it still required? -->
<item name="colorAccent">#03b381</item>
<item name="android:statusBarColor">#1188FF</item> <item name="android:statusBarColor">#1188FF</item>
<item name="android:navigationBarColor">#FF8811</item> <item name="android:navigationBarColor">#FF8811</item>
<item name="android:textColorLink">#000FFF</item>
</style> </style>
<style name="VectorMaterialThemeDebugDark" parent="Theme.MaterialComponents.NoActionBar"> <style name="VectorMaterialThemeDebugDark" parent="Theme.MaterialComponents.NoActionBar">
<!-- Keep all default value -->
</style>
<style name="VectorMaterialThemeDebugDark.Test">
<item name="colorPrimary">#7F7F00</item> <item name="colorPrimary">#7F7F00</item>
<item name="colorPrimaryVariant">#00FF00</item> <item name="colorPrimaryVariant">#00FF00</item>
<item name="colorOnPrimary">#0000FF</item> <item name="colorOnPrimary">#0000FF</item>
@ -49,11 +56,26 @@
<item name="android:colorBackground">#FF7777</item> <item name="android:colorBackground">#FF7777</item>
<item name="colorOnBackground">#077700</item> <item name="colorOnBackground">#077700</item>
<!-- TODO is it still required? -->
<item name="colorAccent">#03b381</item>
<item name="android:statusBarColor">#1188FF</item> <item name="android:statusBarColor">#1188FF</item>
<item name="android:navigationBarColor">#FF8811</item> <item name="android:navigationBarColor">#FF8811</item>
<item name="android:textColorLink">#000FFF</item>
</style>
<style name="DebugTextColorDemo">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">match_parent</item>
<item name="android:padding">4dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">16sp</item>
</style>
<style name="DebugTextColorDemo.White">
<item name="android:textColor">#FFFFFF</item>
</style>
<style name="DebugTextColorDemo.Black">
<item name="android:textColor">#000000</item>
</style> </style>
</resources> </resources>

View File

@ -1,222 +0,0 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.animations.behavior
import android.animation.ArgbEvaluator
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.withStyledAttributes
import im.vector.app.R
import kotlin.math.abs
private const val UNSPECIFIED_INT = Integer.MAX_VALUE
private val UNSPECIFIED_FLOAT = Float.MAX_VALUE
private const val DEPEND_TYPE_HEIGHT = 0
private const val DEPEND_TYPE_WIDTH = 1
private const val DEPEND_TYPE_X = 2
private const val DEPEND_TYPE_Y = 3
class PercentViewBehavior<V : View>(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<V>(context, attrs) {
private var dependType: Int = 0
private var dependViewId: Int = 0
private var dependTarget: Int = 0
private var dependStartX: Int = 0
private var dependStartY: Int = 0
private var dependStartWidth: Int = 0
private var dependStartHeight: Int = 0
private var startX: Int = 0
private var startY: Int = 0
private var startWidth: Int = 0
private var startHeight: Int = 0
private var startBackgroundColor: Int = 0
private var startAlpha: Float = 0f
private var startRotateX: Float = 0f
private var startRotateY: Float = 0f
private var targetX: Int = 0
private var targetY: Int = 0
private var targetWidth: Int = 0
private var targetHeight: Int = 0
private var targetBackgroundColor: Int = 0
private var targetAlpha: Float = 0f
private var targetRotateX: Float = 0f
private var targetRotateY: Float = 0f
/**
* Is the values prepared to be use
*/
private var isPrepared: Boolean = false
init {
context.withStyledAttributes(attrs, R.styleable.PercentViewBehavior) {
dependViewId = getResourceId(R.styleable.PercentViewBehavior_behavior_dependsOn, 0)
dependType = getInt(R.styleable.PercentViewBehavior_behavior_dependType, DEPEND_TYPE_WIDTH)
dependTarget = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_dependTarget, UNSPECIFIED_INT)
targetX = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetX, UNSPECIFIED_INT)
targetY = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetY, UNSPECIFIED_INT)
targetWidth = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetWidth, UNSPECIFIED_INT)
targetHeight = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetHeight, UNSPECIFIED_INT)
targetBackgroundColor = getColor(R.styleable.PercentViewBehavior_behavior_targetBackgroundColor, UNSPECIFIED_INT)
targetAlpha = getFloat(R.styleable.PercentViewBehavior_behavior_targetAlpha, UNSPECIFIED_FLOAT)
targetRotateX = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateX, UNSPECIFIED_FLOAT)
targetRotateY = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateY, UNSPECIFIED_FLOAT)
}
}
private fun prepare(parent: CoordinatorLayout, child: View, dependency: View) {
dependStartX = dependency.x.toInt()
dependStartY = dependency.y.toInt()
dependStartWidth = dependency.width
dependStartHeight = dependency.height
startX = child.x.toInt()
startY = child.y.toInt()
startWidth = child.width
startHeight = child.height
startAlpha = child.alpha
startRotateX = child.rotationX
startRotateY = child.rotationY
// only set the start background color when the background is color drawable
val background = child.background
if (background is ColorDrawable) {
startBackgroundColor = background.color
}
// if parent fitsSystemWindows is true, add status bar height to target y if specified
if (parent.fitsSystemWindows && targetY != UNSPECIFIED_INT) {
var result = 0
val resources = parent.context.resources
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId)
}
targetY += result
}
isPrepared = true
}
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
return dependency.id == dependViewId
}
override fun onDependentViewChanged(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
// first time, prepare values before continue
if (!isPrepared) {
prepare(parent, child, dependency)
}
updateView(child, dependency)
return false
}
override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
val bool = super.onLayoutChild(parent, child, layoutDirection)
if (isPrepared) {
updateView(child, parent.getDependencies(child)[0])
}
return bool
}
/**
* Update the child view from the dependency states
*
* @param child child view
* @param dependency dependency view
*/
private fun updateView(child: V, dependency: View) {
var percent = 0f
var start = 0f
var current = 0f
var end = UNSPECIFIED_INT.toFloat()
when (dependType) {
DEPEND_TYPE_WIDTH -> {
start = dependStartWidth.toFloat()
current = dependency.width.toFloat()
end = dependTarget.toFloat()
}
DEPEND_TYPE_HEIGHT -> {
start = dependStartHeight.toFloat()
current = dependency.height.toFloat()
end = dependTarget.toFloat()
}
DEPEND_TYPE_X -> {
start = dependStartX.toFloat()
current = dependency.x
end = dependTarget.toFloat()
}
DEPEND_TYPE_Y -> {
start = dependStartY.toFloat()
current = dependency.y
end = dependTarget.toFloat()
}
}
// need to define target value according to the depend type, if not then skip
if (end != UNSPECIFIED_INT.toFloat()) {
percent = abs(current - start) / abs(end - start)
}
updateViewWithPercent(child, if (percent > 1f) 1f else percent)
}
private fun updateViewWithPercent(child: View, percent: Float) {
var newX = if (targetX == UNSPECIFIED_INT) 0f else (targetX - startX) * percent
var newY = if (targetY == UNSPECIFIED_INT) 0f else (targetY - startY) * percent
// set scale
if (targetWidth != UNSPECIFIED_INT) {
val newWidth = startWidth + (targetWidth - startWidth) * percent
child.scaleX = newWidth / startWidth
newX -= (startWidth - newWidth) / 2
}
if (targetHeight != UNSPECIFIED_INT) {
val newHeight = startHeight + (targetHeight - startHeight) * percent
child.scaleY = newHeight / startHeight
newY -= (startHeight - newHeight) / 2
}
// set new position
child.translationX = newX
child.translationY = newY
// set alpha
if (targetAlpha != UNSPECIFIED_FLOAT) {
child.alpha = startAlpha + (targetAlpha - startAlpha) * percent
}
// set background color
if (targetBackgroundColor != UNSPECIFIED_INT && startBackgroundColor != 0) {
val evaluator = ArgbEvaluator()
val color = evaluator.evaluate(percent, startBackgroundColor, targetBackgroundColor) as Int
child.setBackgroundColor(color)
}
// set rotation
if (targetRotateX != UNSPECIFIED_FLOAT) {
child.rotationX = startRotateX + (targetRotateX - startRotateX) * percent
}
if (targetRotateY != UNSPECIFIED_FLOAT) {
child.rotationY = startRotateY + (targetRotateY - startRotateY) * percent
}
child.requestLayout()
}
}

View File

@ -32,6 +32,7 @@ import im.vector.app.features.call.conference.VectorJitsiActivity
import im.vector.app.features.call.transfer.CallTransferActivity import im.vector.app.features.call.transfer.CallTransferActivity
import im.vector.app.features.createdirect.CreateDirectRoomActivity import im.vector.app.features.createdirect.CreateDirectRoomActivity
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
import im.vector.app.features.crypto.quads.SharedSecureStorageActivity import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.BootstrapBottomSheet
import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.crypto.verification.VerificationBottomSheet
@ -138,6 +139,7 @@ interface ScreenComponent {
fun inject(activity: LinkHandlerActivity) fun inject(activity: LinkHandlerActivity)
fun inject(activity: MainActivity) fun inject(activity: MainActivity)
fun inject(activity: RoomDirectoryActivity) fun inject(activity: RoomDirectoryActivity)
fun inject(activity: KeysBackupSetupActivity)
fun inject(activity: BugReportActivity) fun inject(activity: BugReportActivity)
fun inject(activity: FilteredRoomsActivity) fun inject(activity: FilteredRoomsActivity)
fun inject(activity: CreateRoomActivity) fun inject(activity: CreateRoomActivity)

View File

@ -18,8 +18,8 @@ package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.databinding.DialogConfirmationWithReasonBinding import im.vector.app.databinding.DialogConfirmationWithReasonBinding
@ -46,7 +46,7 @@ object ConfirmationDialogBuilder {
views.dialogReasonInput.setHint(reasonHintRes) views.dialogReasonInput.setHint(reasonHintRes)
} }
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(titleRes) .setTitle(titleRes)
.setView(layout) .setView(layout)
.setPositiveButton(positiveRes) { _, _ -> .setPositiveButton(positiveRes) { _, _ ->

View File

@ -18,6 +18,7 @@ package im.vector.app.core.dialogs
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.core.platform.Restorable import im.vector.app.core.platform.Restorable
import timber.log.Timber import timber.log.Timber
@ -38,7 +39,7 @@ class DialogLocker(savedInstanceState: Bundle?) : Restorable {
isDialogDisplayed = true isDialogDisplayed = true
} }
fun displayDialog(builder: () -> AlertDialog.Builder): AlertDialog? { fun displayDialog(builder: () -> MaterialAlertDialogBuilder): AlertDialog? {
return if (isDialogDisplayed) { return if (isDialogDisplayed) {
Timber.w("Filtered dialog request") Timber.w("Filtered dialog request")
null null

View File

@ -18,7 +18,7 @@ package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import android.text.Editable import android.text.Editable
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.showPassword import im.vector.app.core.extensions.showPassword
import im.vector.app.core.platform.SimpleTextWatcher import im.vector.app.core.platform.SimpleTextWatcher
@ -31,7 +31,7 @@ class ExportKeysDialog {
fun show(activity: Activity, exportKeyDialogListener: ExportKeyDialogListener) { fun show(activity: Activity, exportKeyDialogListener: ExportKeyDialogListener) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_export_e2e_keys, null) val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_export_e2e_keys, null)
val views = DialogExportE2eKeysBinding.bind(dialogLayout) val views = DialogExportE2eKeysBinding.bind(dialogLayout)
val builder = AlertDialog.Builder(activity) val builder = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.encryption_export_room_keys) .setTitle(R.string.encryption_export_room_keys)
.setView(dialogLayout) .setView(dialogLayout)

View File

@ -16,12 +16,12 @@
package im.vector.app.core.dialogs package im.vector.app.core.dialogs
import androidx.annotation.ColorRes import androidx.annotation.AttrRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import im.vector.app.R import im.vector.app.R
import im.vector.app.features.themes.ThemeUtils
fun AlertDialog.withColoredButton(whichButton: Int, @ColorRes color: Int = R.color.vector_error_color): AlertDialog { fun AlertDialog.withColoredButton(whichButton: Int, @AttrRes color: Int = R.attr.colorError): AlertDialog {
getButton(whichButton)?.setTextColor(ContextCompat.getColor(context, color)) getButton(whichButton)?.setTextColor(ThemeUtils.getColor(context, color))
return this return this
} }

View File

@ -18,11 +18,12 @@ package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import android.net.Uri import android.net.Uri
import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper.Listener
import im.vector.app.core.extensions.insertBeforeLast import im.vector.app.core.extensions.insertBeforeLast
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
@ -101,7 +102,7 @@ class GalleryOrCameraDialogHelper(
} }
fun show() { fun show() {
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.attachment_type_dialog_title) .setTitle(R.string.attachment_type_dialog_title)
.setItems(arrayOf( .setItems(arrayOf(
fragment.getString(R.string.attachment_type_camera), fragment.getString(R.string.attachment_type_camera),

View File

@ -17,7 +17,7 @@
package im.vector.app.core.dialogs package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.databinding.DialogDeviceVerifyBinding import im.vector.app.databinding.DialogDeviceVerifyBinding
import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable
@ -28,7 +28,7 @@ object ManuallyVerifyDialog {
fun show(activity: Activity, cryptoDeviceInfo: CryptoDeviceInfo, onVerified: (() -> Unit)) { fun show(activity: Activity, cryptoDeviceInfo: CryptoDeviceInfo, onVerified: (() -> Unit)) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_device_verify, null) val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_device_verify, null)
val views = DialogDeviceVerifyBinding.bind(dialogLayout) val views = DialogDeviceVerifyBinding.bind(dialogLayout)
val builder = AlertDialog.Builder(activity) val builder = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.cross_signing_verify_by_text) .setTitle(R.string.cross_signing_verify_by_text)
.setView(dialogLayout) .setView(dialogLayout)
.setPositiveButton(R.string.encryption_information_verify) { _, _ -> .setPositiveButton(R.string.encryption_information_verify) { _, _ ->

View File

@ -17,8 +17,8 @@
package im.vector.app.core.dialogs package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.databinding.DialogPhotoOrVideoBinding import im.vector.app.databinding.DialogPhotoOrVideoBinding
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
@ -51,7 +51,7 @@ class PhotoOrVideoDialog(
// Always default to photo // Always default to photo
views.dialogPhotoOrVideoPhoto.isChecked = true views.dialogPhotoOrVideoPhoto.isChecked = true
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.option_take_photo_video) .setTitle(R.string.option_take_photo_video)
.setView(dialogLayout) .setView(dialogLayout)
.setPositiveButton(R.string._continue) { _, _ -> .setPositiveButton(R.string._continue) { _, _ ->
@ -95,7 +95,7 @@ class PhotoOrVideoDialog(
views.dialogPhotoOrVideoVideo.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO views.dialogPhotoOrVideoVideo.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_VIDEO
views.dialogPhotoOrVideoAlwaysAsk.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK views.dialogPhotoOrVideoAlwaysAsk.isChecked = currentMode == VectorPreferences.TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.option_take_photo_video) .setTitle(R.string.option_take_photo_video)
.setView(dialogLayout) .setView(dialogLayout)
.setPositiveButton(R.string.save) { _, _ -> .setPositiveButton(R.string.save) { _, _ ->

View File

@ -21,6 +21,7 @@ import android.content.DialogInterface
import android.text.Editable import android.text.Editable
import android.view.KeyEvent import android.view.KeyEvent
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.showPassword import im.vector.app.core.extensions.showPassword
@ -47,7 +48,7 @@ class PromptPasswordDialog {
views.promptPasswordPasswordReveal.render(passwordVisible) views.promptPasswordPasswordReveal.render(passwordVisible)
} }
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.devices_delete_dialog_title) .setTitle(R.string.devices_delete_dialog_title)
.setView(dialogLayout) .setView(dialogLayout)

View File

@ -16,7 +16,7 @@
package im.vector.app.core.dialogs package im.vector.app.core.dialogs
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
@ -92,7 +92,7 @@ class UnrecognizedCertificateDialog @Inject constructor(
} }
} }
val builder = AlertDialog.Builder(activity) val builder = MaterialAlertDialogBuilder(activity)
val inflater = activity.layoutInflater val inflater = activity.layoutInflater
val layout = inflater.inflate(R.layout.dialog_ssl_fingerprint, null) val layout = inflater.inflate(R.layout.dialog_ssl_fingerprint, null)
val views = DialogSslFingerprintBinding.bind(layout) val views = DialogSslFingerprintBinding.bind(layout)

View File

@ -0,0 +1,24 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.epoxy
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
@EpoxyModelClass(layout = R.layout.item_divider_on_surface)
abstract class BottomSheetDividerItem : VectorEpoxyModel<BottomSheetDividerItem.Holder>() {
class Holder : VectorEpoxyHolder()
}

View File

@ -15,25 +15,10 @@
*/ */
package im.vector.app.core.epoxy package im.vector.app.core.epoxy
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R import im.vector.app.R
/**
* Default background color is for the bottom sheets (R.attr.vctr_list_bottom_sheet_divider_color).
* To use in fragment, set color using R.attr.riotx_list_divider_color
*/
@EpoxyModelClass(layout = R.layout.item_divider) @EpoxyModelClass(layout = R.layout.item_divider)
abstract class DividerItem : VectorEpoxyModel<DividerItem.Holder>() { abstract class DividerItem : VectorEpoxyModel<DividerItem.Holder>() {
@EpoxyAttribute var color: Int = -1
override fun bind(holder: Holder) {
super.bind(holder)
if (color != -1) {
holder.view.setBackgroundColor(color)
}
}
class Holder : VectorEpoxyHolder() class Holder : VectorEpoxyHolder()
} }

View File

@ -79,9 +79,9 @@ abstract class BottomSheetActionItem : VectorEpoxyModel<BottomSheetActionItem.Ho
holder.view.onClick(listener) holder.view.onClick(listener)
holder.startSpace.isVisible = subMenuItem holder.startSpace.isVisible = subMenuItem
val tintColor = if (destructive) { val tintColor = if (destructive) {
ContextCompat.getColor(holder.view.context, R.color.riotx_notice) ThemeUtils.getColor(holder.view.context, R.attr.colorError)
} else { } else {
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
} }
holder.icon.isVisible = showIcon holder.icon.isVisible = showIcon
holder.icon.setImageResource(iconRes) holder.icon.setImageResource(iconRes)
@ -95,9 +95,9 @@ abstract class BottomSheetActionItem : VectorEpoxyModel<BottomSheetActionItem.Ho
holder.selected.isInvisible = !selected holder.selected.isInvisible = !selected
if (showExpand) { if (showExpand) {
val expandDrawable = if (expanded) { val expandDrawable = if (expanded) {
ContextCompat.getDrawable(holder.view.context, R.drawable.ic_material_expand_less_black) ContextCompat.getDrawable(holder.view.context, R.drawable.ic_expand_less)
} else { } else {
ContextCompat.getDrawable(holder.view.context, R.drawable.ic_material_expand_more_black) ContextCompat.getDrawable(holder.view.context, R.drawable.ic_expand_more)
} }
expandDrawable?.also { expandDrawable?.also {
DrawableCompat.setTint(it, tintColor) DrawableCompat.setTint(it, tintColor)

View File

@ -21,7 +21,6 @@ import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.TooltipCompat import androidx.appcompat.widget.TooltipCompat
import androidx.core.content.ContextCompat
import androidx.core.widget.ImageViewCompat import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
@ -31,6 +30,7 @@ import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
@ -45,6 +45,7 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
@EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute lateinit var matrixItem: MatrixItem
@EpoxyAttribute lateinit var stringProvider: StringProvider @EpoxyAttribute lateinit var stringProvider: StringProvider
@EpoxyAttribute lateinit var colorProvider: ColorProvider
@EpoxyAttribute var izLowPriority: Boolean = false @EpoxyAttribute var izLowPriority: Boolean = false
@EpoxyAttribute var izFavorite: Boolean = false @EpoxyAttribute var izFavorite: Boolean = false
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var settingsClickListener: ClickListener? = null @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var settingsClickListener: ClickListener? = null
@ -90,10 +91,10 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
val tintColor: Int val tintColor: Int
if (isLowPriority) { if (isLowPriority) {
description = stringProvider.getString(R.string.room_list_quick_actions_low_priority_remove) description = stringProvider.getString(R.string.room_list_quick_actions_low_priority_remove)
tintColor = ContextCompat.getColor(holder.view.context, R.color.riotx_accent) tintColor = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
} else { } else {
description = stringProvider.getString(R.string.room_list_quick_actions_low_priority_add) description = stringProvider.getString(R.string.room_list_quick_actions_low_priority_add)
tintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) tintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
} }
holder.roomLowPriority.apply { holder.roomLowPriority.apply {
contentDescription = description contentDescription = description
@ -108,11 +109,11 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
if (isFavorite) { if (isFavorite) {
description = stringProvider.getString(R.string.room_list_quick_actions_favorite_remove) description = stringProvider.getString(R.string.room_list_quick_actions_favorite_remove)
holder.roomFavorite.setImageResource(R.drawable.ic_star_green_24dp) holder.roomFavorite.setImageResource(R.drawable.ic_star_green_24dp)
tintColor = ContextCompat.getColor(holder.view.context, R.color.riotx_accent) tintColor = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
} else { } else {
description = stringProvider.getString(R.string.room_list_quick_actions_favorite_add) description = stringProvider.getString(R.string.room_list_quick_actions_favorite_add)
holder.roomFavorite.setImageResource(R.drawable.ic_star_24dp) holder.roomFavorite.setImageResource(R.drawable.ic_star_24dp)
tintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) tintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
} }
holder.roomFavorite.apply { holder.roomFavorite.apply {
contentDescription = description contentDescription = description

View File

@ -19,7 +19,6 @@ package im.vector.app.core.epoxy.profiles
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.ImageViewCompat import androidx.core.widget.ImageViewCompat
import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyAttribute
@ -78,14 +77,14 @@ abstract class ProfileActionItem : VectorEpoxyModel<ProfileActionItem.Holder>()
} }
holder.title.text = title holder.title.text = title
val titleTintColor = if (destructive) { val titleTintColor = if (destructive) {
ContextCompat.getColor(holder.view.context, R.color.riotx_notice) ThemeUtils.getColor(holder.view.context, R.attr.colorError)
} else { } else {
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary) ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)
} }
val iconTintColor = if (destructive) { val iconTintColor = if (destructive) {
ContextCompat.getColor(holder.view.context, R.color.riotx_notice) ThemeUtils.getColor(holder.view.context, R.attr.colorError)
} else { } else {
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
} }
holder.title.setTextColor(titleTintColor) holder.title.setTextColor(titleTintColor)
holder.subtitle.setTextOrHide(subtitle) holder.subtitle.setTextOrHide(subtitle)
@ -119,7 +118,7 @@ abstract class ProfileActionItem : VectorEpoxyModel<ProfileActionItem.Holder>()
val tintColorSecondary = if (destructive) { val tintColorSecondary = if (destructive) {
titleTintColor titleTintColor
} else { } else {
ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
} }
holder.editable.setImageResource(editableRes) holder.editable.setImageResource(editableRes)
ImageViewCompat.setImageTintList(holder.editable, ColorStateList.valueOf(tintColorSecondary)) ImageViewCompat.setImageTintList(holder.editable, ColorStateList.valueOf(tintColorSecondary))

View File

@ -34,7 +34,6 @@ fun EpoxyController.buildProfileSection(title: String) {
fun EpoxyController.buildProfileAction( fun EpoxyController.buildProfileAction(
id: String, id: String,
title: String, title: String,
dividerColor: Int,
subtitle: String? = null, subtitle: String? = null,
editable: Boolean = true, editable: Boolean = true,
@DrawableRes icon: Int = 0, @DrawableRes icon: Int = 0,
@ -65,7 +64,6 @@ fun EpoxyController.buildProfileAction(
if (divider) { if (divider) {
dividerItem { dividerItem {
id("divider_$title") id("divider_$title")
color(dividerColor)
} }
} }
} }

View File

@ -16,13 +16,13 @@
package im.vector.app.core.extensions package im.vector.app.core.extensions
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import com.airbnb.epoxy.EpoxyVisibilityTracker import com.airbnb.epoxy.EpoxyVisibilityTracker
import im.vector.app.R
/** /**
* Apply a Vertical LinearLayout Manager to the recyclerView and set the adapter from the epoxy controller * Apply a Vertical LinearLayout Manager to the recyclerView and set the adapter from the epoxy controller
@ -30,7 +30,8 @@ import im.vector.app.R
fun RecyclerView.configureWith(epoxyController: EpoxyController, fun RecyclerView.configureWith(epoxyController: EpoxyController,
itemAnimator: RecyclerView.ItemAnimator? = null, itemAnimator: RecyclerView.ItemAnimator? = null,
viewPool: RecyclerView.RecycledViewPool? = null, viewPool: RecyclerView.RecycledViewPool? = null,
showDivider: Boolean = false, @DrawableRes
dividerDrawable: Int? = null,
hasFixedSize: Boolean = true, hasFixedSize: Boolean = true,
disableItemAnimation: Boolean = false) { disableItemAnimation: Boolean = false) {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false).apply { layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false).apply {
@ -42,10 +43,10 @@ fun RecyclerView.configureWith(epoxyController: EpoxyController,
} else { } else {
itemAnimator?.let { this.itemAnimator = it } itemAnimator?.let { this.itemAnimator = it }
} }
if (showDivider) { dividerDrawable?.let { divider ->
addItemDecoration( addItemDecoration(
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply { DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
ContextCompat.getDrawable(context, R.drawable.divider_horizontal)?.let { ContextCompat.getDrawable(context, divider)?.let {
setDrawable(it) setDrawable(it)
} }
} }

View File

@ -26,7 +26,6 @@ import android.text.style.UnderlineSpan
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -54,13 +53,13 @@ fun TextView.setTextOrHide(newText: CharSequence?, hideWhenBlank: Boolean = true
* Set text with a colored part * Set text with a colored part
* @param fullTextRes the resource id of the full text. Value MUST contains a parameter for string, which will be replaced by the colored part * @param fullTextRes the resource id of the full text. Value MUST contains a parameter for string, which will be replaced by the colored part
* @param coloredTextRes the resource id of the colored part of the text * @param coloredTextRes the resource id of the colored part of the text
* @param colorAttribute attribute of the color. Default to colorAccent * @param colorAttribute attribute of the color. Default to colorPrimary
* @param underline true to also underline the text. Default to false * @param underline true to also underline the text. Default to false
* @param onClick attributes to handle click on the colored part if needed * @param onClick attributes to handle click on the colored part if needed
*/ */
fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int, fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
@StringRes coloredTextRes: Int, @StringRes coloredTextRes: Int,
@AttrRes colorAttribute: Int = R.attr.colorAccent, @AttrRes colorAttribute: Int = R.attr.colorPrimary,
underline: Boolean = false, underline: Boolean = false,
onClick: (() -> Unit)? = null) { onClick: (() -> Unit)? = null) {
val coloredPart = resources.getString(coloredTextRes) val coloredPart = resources.getString(coloredTextRes)
@ -95,9 +94,9 @@ fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
} }
} }
fun TextView.setLeftDrawable(@DrawableRes iconRes: Int, @ColorRes tintColor: Int? = null) { fun TextView.setLeftDrawable(@DrawableRes iconRes: Int, @AttrRes tintColor: Int? = null) {
val icon = if (tintColor != null) { val icon = if (tintColor != null) {
val tint = ContextCompat.getColor(context, tintColor) val tint = ThemeUtils.getColor(context, tintColor)
ContextCompat.getDrawable(context, iconRes)?.also { ContextCompat.getDrawable(context, iconRes)?.also {
DrawableCompat.setTint(it.mutate(), tint) DrawableCompat.setTint(it.mutate(), tint)
} }

View File

@ -122,6 +122,10 @@ class BadgeFloatingActionButton @JvmOverloads constructor(
} }
init { init {
if (isInEditMode) {
count = 3
}
countStr = countStr(count) countStr = countStr(count)
textPaint.getTextBounds(countStr, 0, countStr.length, counterTextBounds) textPaint.getTextBounds(countStr, 0, countStr.length, counterTextBounds)
countMaxStr = "$maxCount+" countMaxStr = "$maxCount+"

View File

@ -27,7 +27,6 @@ import android.view.View
import android.view.WindowInsetsController import android.view.WindowInsetsController
import android.view.WindowManager import android.view.WindowManager
import android.widget.TextView import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.annotation.MenuRes import androidx.annotation.MenuRes
@ -456,7 +455,6 @@ abstract class VectorBaseActivity<VB: ViewBinding> : AppCompatActivity(), HasScr
if (menuRes != -1) { if (menuRes != -1) {
menuInflater.inflate(menuRes, menu) menuInflater.inflate(menuRes, menu)
ThemeUtils.tintMenuIcons(menu, ThemeUtils.getColor(this, getMenuTint()))
return true return true
} }
@ -584,9 +582,6 @@ abstract class VectorBaseActivity<VB: ViewBinding> : AppCompatActivity(), HasScr
@MenuRes @MenuRes
open fun getMenuRes() = -1 open fun getMenuRes() = -1
@AttrRes
open fun getMenuTint() = R.attr.vctr_icon_tint_on_light_action_bar_color
/** /**
* Return a object containing other themes for this activity * Return a object containing other themes for this activity
*/ */

View File

@ -29,12 +29,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.airbnb.mvrx.BaseMvRxFragment import com.airbnb.mvrx.BaseMvRxFragment
import com.bumptech.glide.util.Util.assertMainThread import com.bumptech.glide.util.Util.assertMainThread
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.view.clicks import com.jakewharton.rxbinding3.view.clicks
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.DaggerScreenComponent import im.vector.app.core.di.DaggerScreenComponent
@ -290,7 +290,7 @@ abstract class VectorBaseFragment<VB: ViewBinding> : BaseMvRxFragment(), HasScre
* ========================================================================================== */ * ========================================================================================== */
protected fun displayErrorDialog(throwable: Throwable) { protected fun displayErrorDialog(throwable: Throwable) {
AlertDialog.Builder(requireActivity()) MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(throwable)) .setMessage(errorFormatter.toHumanReadable(throwable))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -107,7 +107,7 @@ open class VectorPreference : Preference {
val icon = holder.findViewById(android.R.id.icon) as? ImageView val icon = holder.findViewById(android.R.id.icon) as? ImageView
icon?.let { icon?.let {
val color = ThemeUtils.getColor(context, R.attr.riotx_header_panel_text_secondary) val color = ThemeUtils.getColor(context, R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(it, ColorStateList.valueOf(color)) ImageViewCompat.setImageTintList(it, ColorStateList.valueOf(color))
} }
} }
@ -116,7 +116,7 @@ open class VectorPreference : Preference {
currentHighlightAnimator?.cancel() currentHighlightAnimator?.cancel()
if (isHighlighted) { if (isHighlighted) {
val colorFrom = Color.TRANSPARENT val colorFrom = Color.TRANSPARENT
val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorAccent) val colorTo = ThemeUtils.getColor(itemView.context, R.attr.colorPrimary)
currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply { currentHighlightAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
duration = 250 // milliseconds duration = 250 // milliseconds
addUpdateListener { animator -> addUpdateListener { animator ->

View File

@ -48,7 +48,7 @@ class VectorPreferenceCategory : PreferenceCategory {
val titleTextView = holder.findViewById(android.R.id.title) as? TextView val titleTextView = holder.findViewById(android.R.id.title) as? TextView
titleTextView?.setTypeface(null, Typeface.BOLD) titleTextView?.setTypeface(null, Typeface.BOLD)
titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_primary)) titleTextView?.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_primary))
// "isIconSpaceReserved = false" does not work for preference category, so remove the padding // "isIconSpaceReserved = false" does not work for preference category, so remove the padding
if (!isIconSpaceReserved) { if (!isIconSpaceReserved) {

View File

@ -42,7 +42,7 @@ abstract class BottomSheetGenericController<State : BottomSheetGenericState, Act
subTitle(host.getSubTitle()) subTitle(host.getSubTitle())
} }
// dividerItem { // bottomSheetDividerItem {
// id("title_separator") // id("title_separator")
// } // }
} }

View File

@ -50,7 +50,7 @@ abstract class GenericButtonItem : VectorEpoxyModel<GenericButtonItem.Holder>()
override fun bind(holder: Holder) { override fun bind(holder: Holder) {
super.bind(holder) super.bind(holder)
holder.button.text = text holder.button.text = text
val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary) val textColor = textColor ?: ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary)
holder.button.setTextColor(textColor) holder.button.setTextColor(textColor)
if (iconRes != null) { if (iconRes != null) {
holder.button.setIconResource(iconRes!!) holder.button.setIconResource(iconRes!!)

View File

@ -64,7 +64,7 @@ abstract class GenericFooterItem : VectorEpoxyModel<GenericFooterItem.Holder>()
if (textColor != null) { if (textColor != null) {
holder.text.setTextColor(textColor!!) holder.text.setTextColor(textColor!!)
} else { } else {
holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)) holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary))
} }
holder.view.onClick(itemClickAction) holder.view.onClick(itemClickAction)

View File

@ -72,7 +72,7 @@ abstract class GenericPillItem : VectorEpoxyModel<GenericPillItem.Holder>() {
holder.imageView.isVisible = false holder.imageView.isVisible = false
} }
if (tintIcon) { if (tintIcon) {
val iconTintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary) val iconTintColor = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(holder.imageView, ColorStateList.valueOf(iconTintColor)) ImageViewCompat.setImageTintList(holder.imageView, ColorStateList.valueOf(iconTintColor))
} else { } else {
ImageViewCompat.setImageTintList(holder.imageView, null) ImageViewCompat.setImageTintList(holder.imageView, null)

View File

@ -76,7 +76,7 @@ abstract class GenericWithValueItem : VectorEpoxyModel<GenericWithValueItem.Hold
if (valueColorInt != null) { if (valueColorInt != null) {
holder.valueText.setTextColor(valueColorInt!!) holder.valueText.setTextColor(valueColorInt!!)
} else { } else {
holder.valueText.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_primary)) holder.valueText.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_primary))
} }
holder.view.onClick(itemClickAction) holder.view.onClick(itemClickAction)

View File

@ -21,7 +21,6 @@ import android.content.res.ColorStateList
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
@ -109,7 +108,7 @@ class BottomSheetActionButton @JvmOverloads constructor(
rightIcon = getDrawable(R.styleable.BottomSheetActionButton_rightIcon) rightIcon = getDrawable(R.styleable.BottomSheetActionButton_rightIcon)
tint = getColor(R.styleable.BottomSheetActionButton_tint, ThemeUtils.getColor(context, android.R.attr.textColor)) tint = getColor(R.styleable.BottomSheetActionButton_tint, ThemeUtils.getColor(context, android.R.attr.textColor))
titleTextColor = getColor(R.styleable.BottomSheetActionButton_titleTextColor, ContextCompat.getColor(context, R.color.riotx_accent)) titleTextColor = getColor(R.styleable.BottomSheetActionButton_titleTextColor, ThemeUtils.getColor(context, R.attr.colorPrimary))
} }
} }
} }

View File

@ -16,8 +16,8 @@
package im.vector.app.core.ui.views package im.vector.app.core.ui.views
import androidx.cardview.widget.CardView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.card.MaterialCardView
import im.vector.app.core.epoxy.onClick import im.vector.app.core.epoxy.onClick
import im.vector.app.features.call.utils.EglUtils import im.vector.app.features.call.utils.EglUtils
import im.vector.app.features.call.webrtc.WebRtcCall import im.vector.app.features.call.webrtc.WebRtcCall
@ -29,7 +29,7 @@ class KnownCallsViewHolder {
private var activeCallPiP: SurfaceViewRenderer? = null private var activeCallPiP: SurfaceViewRenderer? = null
private var currentCallsView: CurrentCallsView? = null private var currentCallsView: CurrentCallsView? = null
private var pipWrapper: CardView? = null private var pipWrapper: MaterialCardView? = null
private var currentCall: WebRtcCall? = null private var currentCall: WebRtcCall? = null
private var calls: List<WebRtcCall> = emptyList() private var calls: List<WebRtcCall> = emptyList()
@ -83,7 +83,10 @@ class KnownCallsViewHolder {
} }
} }
fun bind(activeCallPiP: SurfaceViewRenderer, activeCallView: CurrentCallsView, pipWrapper: CardView, interactionListener: CurrentCallsView.Callback) { fun bind(activeCallPiP: SurfaceViewRenderer,
activeCallView: CurrentCallsView,
pipWrapper: MaterialCardView,
interactionListener: CurrentCallsView.Callback) {
this.activeCallPiP = activeCallPiP this.activeCallPiP = activeCallPiP
this.currentCallsView = activeCallView this.currentCallsView = activeCallView
this.pipWrapper = pipWrapper this.pipWrapper = pipWrapper

View File

@ -102,7 +102,7 @@ class NotificationAreaView @JvmOverloads constructor(
} }
} }
views.roomNotificationMessage.text = message views.roomNotificationMessage.text = message
views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary)) views.roomNotificationMessage.setTextColor(ThemeUtils.getColor(context, R.attr.vctr_content_secondary))
} }
private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) { private fun renderResourceLimitExceededError(state: State.ResourceLimitExceededError) {

View File

@ -41,13 +41,13 @@ class SendStateImageView @JvmOverloads constructor(
isVisible = when (sendState) { isVisible = when (sendState) {
SendStateDecoration.SENDING_NON_MEDIA -> { SendStateDecoration.SENDING_NON_MEDIA -> {
setImageResource(R.drawable.ic_sending_message) setImageResource(R.drawable.ic_sending_message)
imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.riotx_text_tertiary)) imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary))
contentDescription = context.getString(R.string.event_status_a11y_sending) contentDescription = context.getString(R.string.event_status_a11y_sending)
true true
} }
SendStateDecoration.SENT -> { SendStateDecoration.SENT -> {
setImageResource(R.drawable.ic_message_sent) setImageResource(R.drawable.ic_message_sent)
imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.riotx_text_tertiary)) imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary))
contentDescription = context.getString(R.string.event_status_a11y_sent) contentDescription = context.getString(R.string.event_status_a11y_sent)
true true
} }

View File

@ -19,7 +19,7 @@ package im.vector.app.core.utils
import android.content.Context import android.content.Context
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
/** /**
* Open a web view above the current activity. * Open a web view above the current activity.
@ -33,7 +33,7 @@ fun Context.displayInWebView(url: String) {
wv.webViewClient = WebViewClient() wv.webViewClient = WebViewClient()
wv.loadUrl(url) wv.loadUrl(url)
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setView(wv) .setView(wv)
.setPositiveButton(android.R.string.ok, null) .setPositiveButton(android.R.string.ok, null)
.show() .show()

View File

@ -56,7 +56,6 @@ import timber.log.Timber
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
import java.lang.IllegalStateException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -100,8 +99,8 @@ fun openUrlInChromeCustomTab(context: Context,
CustomTabsIntent.Builder() CustomTabsIntent.Builder()
.setDefaultColorSchemeParams( .setDefaultColorSchemeParams(
CustomTabColorSchemeParams.Builder() CustomTabColorSchemeParams.Builder()
.setToolbarColor(ThemeUtils.getColor(context, R.attr.riotx_background)) .setToolbarColor(ThemeUtils.getColor(context, android.R.attr.colorBackground))
.setNavigationBarColor(ThemeUtils.getColor(context, R.attr.riotx_background)) .setNavigationBarColor(ThemeUtils.getColor(context, android.R.attr.colorBackground))
.build() .build()
) )
.setColorScheme( .setColorScheme(

View File

@ -22,10 +22,10 @@ import org.billcarsonfr.jsonviewer.JSonViewerStyleProvider
fun createJSonViewerStyleProvider(colorProvider: ColorProvider): JSonViewerStyleProvider { fun createJSonViewerStyleProvider(colorProvider: ColorProvider): JSonViewerStyleProvider {
return JSonViewerStyleProvider( return JSonViewerStyleProvider(
keyColor = colorProvider.getColor(R.color.riotx_accent), keyColor = colorProvider.getColorFromAttribute(R.attr.colorPrimary),
secondaryColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary), secondaryColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary),
stringColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color), stringColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color),
baseColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_primary), baseColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_primary),
booleanColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color), booleanColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color),
numberColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color) numberColor = colorProvider.getColorFromAttribute(R.attr.vctr_notice_text_color)
) )

View File

@ -25,10 +25,10 @@ import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import timber.log.Timber import timber.log.Timber
@ -222,7 +222,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
// if some permissions were already denied: display a dialog to the user before asking again. // if some permissions were already denied: display a dialog to the user before asking again.
if (permissionListAlreadyDenied.isNotEmpty() && rationaleMessage != 0) { if (permissionListAlreadyDenied.isNotEmpty() && rationaleMessage != 0) {
// display the dialog with the info text // display the dialog with the info text
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.permissions_rationale_popup_title) .setTitle(R.string.permissions_rationale_popup_title)
.setMessage(rationaleMessage) .setMessage(rationaleMessage)
.setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() } .setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() }
@ -246,7 +246,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
TODO() TODO()
/* /*
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setIcon(android.R.drawable.ic_dialog_info) .setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.permissions_rationale_popup_title) .setTitle(R.string.permissions_rationale_popup_title)
.setMessage(R.string.permissions_msg_contacts_warning_other_androids) .setMessage(R.string.permissions_msg_contacts_warning_other_androids)

View File

@ -20,10 +20,10 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
@ -208,7 +208,7 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
private fun displayError(failure: Throwable) { private fun displayError(failure: Throwable) {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(failure)) .setMessage(errorFormatter.toHumanReadable(failure))
.setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() } .setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() }

View File

@ -20,10 +20,10 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.activityViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetCallControlsBinding import im.vector.app.databinding.BottomSheetCallControlsBinding
@ -105,7 +105,7 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetC
} }
} }
} }
AlertDialog.Builder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setItems(soundDevices.toTypedArray()) { d, n -> .setItems(soundDevices.toTypedArray()) { d, n ->
d.cancel() d.cancel()
when (soundDevices[n].toString()) { when (soundDevices[n].toString()) {

View File

@ -26,7 +26,6 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
@ -35,6 +34,7 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
@ -359,8 +359,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
private fun onErrorTimoutConnect(turn: TurnServerResponse?) { private fun onErrorTimoutConnect(turn: TurnServerResponse?) {
Timber.d("## VOIP onErrorTimoutConnect $turn") Timber.d("## VOIP onErrorTimoutConnect $turn")
// TODO ask to use default stun, etc... // TODO ask to use default stun, etc...
AlertDialog MaterialAlertDialogBuilder(this)
.Builder(this)
.setTitle(R.string.call_failed_no_connection) .setTitle(R.string.call_failed_no_connection)
.setMessage(getString(R.string.call_failed_no_connection_description)) .setMessage(getString(R.string.call_failed_no_connection_description))
.setNegativeButton(R.string.ok) { _, _ -> .setNegativeButton(R.string.ok) { _, _ ->

View File

@ -26,7 +26,6 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
@ -34,6 +33,7 @@ import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.facebook.react.modules.core.PermissionListener import com.facebook.react.modules.core.PermissionListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
@ -103,7 +103,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
} }
private fun handleConfirmSwitching(action: JitsiCallViewEvents.ConfirmSwitchingConference) { private fun handleConfirmSwitching(action: JitsiCallViewEvents.ConfirmSwitchingConference) {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_warning) .setTitle(R.string.dialog_title_warning)
.setMessage(R.string.jitsi_leave_conf_to_join_another_one_content) .setMessage(R.string.jitsi_leave_conf_to_join_another_one_content)
.setPositiveButton(R.string.action_switch) { _, _ -> .setPositiveButton(R.string.action_switch) { _, _ ->

View File

@ -57,7 +57,7 @@ class DialPadFragment : Fragment() {
dialpadView.findViewById<View>(R.id.dialpad_key_voicemail).isVisible = false dialpadView.findViewById<View>(R.id.dialpad_key_voicemail).isVisible = false
digits = dialpadView.digits as? DigitsEditText digits = dialpadView.digits as? DigitsEditText
digits?.isCursorVisible = cursorVisible digits?.isCursorVisible = cursorVisible
digits?.setTextColor(ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.riotx_text_primary)) digits?.setTextColor(ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.vctr_content_primary))
dialpadView.findViewById<View>(R.id.zero).setOnClickListener { append('0') } dialpadView.findViewById<View>(R.id.zero).setOnClickListener { append('0') }
if (enablePlus) { if (enablePlus) {
dialpadView.findViewById<View>(R.id.zero).setOnLongClickListener { dialpadView.findViewById<View>(R.id.zero).setOnLongClickListener {
@ -91,7 +91,7 @@ class DialPadFragment : Fragment() {
clear() clear()
true true
} }
val tintColor = ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.riotx_text_secondary) val tintColor = ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.vctr_content_secondary)
ImageViewCompat.setImageTintList(dialpadView.deleteButton, ColorStateList.valueOf(tintColor)) ImageViewCompat.setImageTintList(dialpadView.deleteButton, ColorStateList.valueOf(tintColor))
} else { } else {
dialpadView.deleteButton.isVisible = false dialpadView.deleteButton.isVisible = false

View File

@ -17,7 +17,7 @@
package im.vector.app.features.consent package im.vector.app.features.consent
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.dialogs.DialogLocker import im.vector.app.core.dialogs.DialogLocker
import im.vector.app.core.platform.Restorable import im.vector.app.core.platform.Restorable
@ -37,7 +37,7 @@ class ConsentNotGivenHelper(private val activity: Activity,
*/ */
fun displayDialog(consentUri: String, homeServerHost: String) { fun displayDialog(consentUri: String, homeServerHost: String) {
dialogLocker.displayDialog { dialogLocker.displayDialog {
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.settings_app_term_conditions) .setTitle(R.string.settings_app_term_conditions)
.setMessage(activity.getString(R.string.dialog_user_consent_content, homeServerHost)) .setMessage(activity.getString(R.string.dialog_user_consent_content, homeServerHost))
.setPositiveButton(R.string.dialog_user_consent_submit) { _, _ -> .setPositiveButton(R.string.dialog_user_consent_submit) { _, _ ->

View File

@ -20,10 +20,10 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.jakewharton.rxbinding3.widget.checkedChanges import com.jakewharton.rxbinding3.widget.checkedChanges
import com.jakewharton.rxbinding3.widget.textChanges import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.app.R import im.vector.app.R
@ -76,7 +76,7 @@ class ContactsBookFragment @Inject constructor(
private fun setupConsentView() { private fun setupConsentView() {
views.phoneBookSearchForMatrixContacts.setOnClickListener { views.phoneBookSearchForMatrixContacts.setOnClickListener {
withState(contactsBookViewModel) { state -> withState(contactsBookViewModel) { state ->
AlertDialog.Builder(requireActivity()) MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.identity_server_consent_dialog_title) .setTitle(R.string.identity_server_consent_dialog_title)
.setMessage(getString(R.string.identity_server_consent_dialog_content, state.identityServerUrl ?: "")) .setMessage(getString(R.string.identity_server_consent_dialog_content, state.identityServerUrl ?: ""))
.setPositiveButton(R.string.yes) { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->

View File

@ -22,12 +22,12 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
@ -171,7 +171,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
finish() finish()
} }
is CreateRoomFailure.CreatedWithFederationFailure -> { is CreateRoomFailure.CreatedWithFederationFailure -> {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.create_room_federation_error, error.matrixError.message)) .setMessage(getString(R.string.create_room_federation_error, error.matrixError.message))
.setCancelable(false) .setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> finish() } .setPositiveButton(R.string.ok) { _, _ -> finish() }
@ -184,7 +184,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
} else { } else {
errorFormatter.toHumanReadable(error) errorFormatter.toHumanReadable(error)
} }
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setMessage(message) .setMessage(message)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()

View File

@ -18,35 +18,24 @@ package im.vector.app.features.crypto.keys
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.extensions.foldToCallback import javax.inject.Inject
import org.matrix.android.sdk.internal.util.awaitCallback
class KeysExporter(private val session: Session) {
class KeysExporter @Inject constructor(
private val session: Session,
private val context: Context
) {
/** /**
* Export keys and return the file path with the callback * Export keys and write them to the provided uri
*/ */
fun export(context: Context, password: String, uri: Uri, callback: MatrixCallback<Boolean>) { suspend fun export(password: String, uri: Uri) {
session.coroutineScope.launch(Dispatchers.Main) { return withContext(Dispatchers.IO) {
runCatching { val data = session.cryptoService().exportRoomKeys(password)
withContext(Dispatchers.IO) { context.contentResolver.openOutputStream(uri)
val data = awaitCallback<ByteArray> { session.cryptoService().exportRoomKeys(password, it) } ?.use { it.write(data) }
val os = context.contentResolver?.openOutputStream(uri) ?: throw IllegalStateException("Unable to open file for writting")
if (os == null) {
false
} else {
os.write(data)
os.flush()
true
}
}
}.foldToCallback(callback)
} }
} }
} }

View File

@ -20,49 +20,27 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.resources.openResource import im.vector.app.core.resources.openResource
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
import org.matrix.android.sdk.internal.extensions.foldToCallback import javax.inject.Inject
import org.matrix.android.sdk.internal.util.awaitCallback
import timber.log.Timber
class KeysImporter(private val session: Session) {
class KeysImporter @Inject constructor(
private val context: Context,
private val session: Session
) {
/** /**
* Import keys from provided Uri * Import keys from provided Uri
*/ */
fun import(context: Context, suspend fun import(uri: Uri,
uri: Uri, mimetype: String?,
mimetype: String?, password: String): ImportRoomKeysResult {
password: String, return withContext(Dispatchers.IO) {
callback: MatrixCallback<ImportRoomKeysResult>) { val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
session.coroutineScope.launch(Dispatchers.Main) { val stream = resource?.mContentStream ?: throw Exception("Error")
runCatching { val data = stream.use { it.readBytes() }
withContext(Dispatchers.IO) { session.cryptoService().importRoomKeys(data, password, null)
val resource = openResource(context, uri, mimetype ?: getMimeTypeFromUri(context, uri))
if (resource?.mContentStream == null) {
throw Exception("Error")
}
val data: ByteArray
try {
data = resource.mContentStream!!.use { it.readBytes() }
} catch (e: Exception) {
Timber.e(e, "## importKeys()")
throw e
}
awaitCallback<ImportRoomKeysResult> {
session.cryptoService().importRoomKeys(data, password, null, it)
}
}
}.foldToCallback(callback)
} }
} }
} }

View File

@ -18,7 +18,7 @@ package im.vector.app.features.crypto.keysbackup.restore
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.addFragmentToBackstack
import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.observeEvent
@ -66,7 +66,7 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
} }
viewModel.keyVersionResultError.observeEvent(this) { message -> viewModel.keyVersionResultError.observeEvent(this) { message ->
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error) .setTitle(R.string.unknown_error)
.setMessage(message) .setMessage(message)
.setCancelable(false) .setCancelable(false)
@ -97,7 +97,7 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
launch4SActivity() launch4SActivity()
} }
KeysBackupRestoreSharedViewModel.NAVIGATE_FAILED_TO_LOAD_4S -> { KeysBackupRestoreSharedViewModel.NAVIGATE_FAILED_TO_LOAD_4S -> {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error) .setTitle(R.string.unknown_error)
.setMessage(R.string.error_failed_to_import_keys) .setMessage(R.string.error_failed_to_import_keys)
.setCancelable(false) .setCancelable(false)

View File

@ -17,10 +17,10 @@ package im.vector.app.features.crypto.keysbackup.settings
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.replaceFragment
@ -60,7 +60,7 @@ class KeysBackupManageActivity : SimpleFragmentActivity() {
is Fail -> { is Fail -> {
updateWaitingView(null) updateWaitingView(null)
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error) .setTitle(R.string.unknown_error)
.setMessage(getString(R.string.keys_backup_get_version_error, asyncDelete.error.localizedMessage)) .setMessage(getString(R.string.keys_backup_get_version_error, asyncDelete.error.localizedMessage))
.setCancelable(false) .setCancelable(false)

View File

@ -19,9 +19,9 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
@ -72,7 +72,7 @@ class KeysBackupSettingsFragment @Inject constructor(private val keysBackupSetti
override fun didSelectDeleteSetupMessageRecovery() { override fun didSelectDeleteSetupMessageRecovery() {
activity?.let { activity?.let {
AlertDialog.Builder(it) MaterialAlertDialogBuilder(it)
.setTitle(R.string.keys_backup_settings_delete_confirm_title) .setTitle(R.string.keys_backup_settings_delete_confirm_title)
.setMessage(R.string.keys_backup_settings_delete_confirm_message) .setMessage(R.string.keys_backup_settings_delete_confirm_message)
.setCancelable(false) .setCancelable(false)

View File

@ -18,10 +18,13 @@ package im.vector.app.features.crypto.keysbackup.setup
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.appcompat.app.AlertDialog import android.net.Uri
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.dialogs.ExportKeysDialog import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.observeEvent import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.queryExportKeys import im.vector.app.core.extensions.queryExportKeys
@ -30,7 +33,8 @@ import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.features.crypto.keys.KeysExporter import im.vector.app.features.crypto.keys.KeysExporter
import org.matrix.android.sdk.api.MatrixCallback import kotlinx.coroutines.launch
import javax.inject.Inject
class KeysBackupSetupActivity : SimpleFragmentActivity() { class KeysBackupSetupActivity : SimpleFragmentActivity() {
@ -38,6 +42,13 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
private lateinit var viewModel: KeysBackupSetupSharedViewModel private lateinit var viewModel: KeysBackupSetupSharedViewModel
@Inject lateinit var keysExporter: KeysExporter
override fun injectWith(injector: ScreenComponent) {
super.injectWith(injector)
injector.inject(this)
}
override fun initUiAndData() { override fun initUiAndData() {
super.initUiAndData() super.initUiAndData()
if (isFirstCreation()) { if (isFirstCreation()) {
@ -82,7 +93,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
finish() finish()
} }
KeysBackupSetupSharedViewModel.NAVIGATE_PROMPT_REPLACE -> { KeysBackupSetupSharedViewModel.NAVIGATE_PROMPT_REPLACE -> {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.keys_backup_setup_override_backup_prompt_tile) .setTitle(R.string.keys_backup_setup_override_backup_prompt_tile)
.setMessage(R.string.keys_backup_setup_override_backup_prompt_description) .setMessage(R.string.keys_backup_setup_override_backup_prompt_description)
.setPositiveButton(R.string.keys_backup_setup_override_replace) { _, _ -> .setPositiveButton(R.string.keys_backup_setup_override_replace) { _, _ ->
@ -100,7 +111,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
viewModel.prepareRecoverFailError.observe(this) { error -> viewModel.prepareRecoverFailError.observe(this) { error ->
if (error != null) { if (error != null) {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.unknown_error) .setTitle(R.string.unknown_error)
.setMessage(error.localizedMessage) .setMessage(error.localizedMessage)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
@ -113,7 +124,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
viewModel.creatingBackupError.observe(this) { error -> viewModel.creatingBackupError.observe(this) { error ->
if (error != null) { if (error != null) {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.unexpected_error) .setTitle(R.string.unexpected_error)
.setMessage(error.localizedMessage) .setMessage(error.localizedMessage)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
@ -132,30 +143,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
ExportKeysDialog().show(this, object : ExportKeysDialog.ExportKeyDialogListener { ExportKeysDialog().show(this, object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) { override fun onPassphrase(passphrase: String) {
showWaitingView() showWaitingView()
export(passphrase, uri)
KeysExporter(session)
.export(this@KeysBackupSetupActivity,
passphrase,
uri,
object : MatrixCallback<Boolean> {
override fun onSuccess(data: Boolean) {
if (data) {
toast(getString(R.string.encryption_exported_successfully))
Intent().apply {
putExtra(MANUAL_EXPORT, true)
}.let {
setResult(Activity.RESULT_OK, it)
finish()
}
}
hideWaitingView()
}
override fun onFailure(failure: Throwable) {
toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
hideWaitingView()
}
})
} }
}) })
} else { } else {
@ -165,12 +153,26 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
} }
} }
private fun export(passphrase: String, uri: Uri) {
lifecycleScope.launch {
try {
keysExporter.export(passphrase, uri)
toast(getString(R.string.encryption_exported_successfully))
setResult(Activity.RESULT_OK, Intent().apply { putExtra(MANUAL_EXPORT, true) })
finish()
} catch (failure: Throwable) {
toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
}
hideWaitingView()
}
}
override fun onBackPressed() { override fun onBackPressed() {
if (viewModel.shouldPromptOnBack) { if (viewModel.shouldPromptOnBack) {
if (waitingView?.isVisible == true) { if (waitingView?.isVisible == true) {
return return
} }
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.keys_backup_setup_skip_title) .setTitle(R.string.keys_backup_setup_skip_title)
.setMessage(R.string.keys_backup_setup_skip_msg) .setMessage(R.string.keys_backup_setup_skip_msg)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@ -23,11 +23,11 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import arrow.core.Try import arrow.core.Try
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
@ -177,7 +177,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
.fold( .fold(
{ throwable -> { throwable ->
activity?.let { activity?.let {
AlertDialog.Builder(it) MaterialAlertDialogBuilder(it)
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(throwable)) .setMessage(errorFormatter.toHumanReadable(throwable))
} }
@ -185,7 +185,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
{ {
viewModel.copyHasBeenMade = true viewModel.copyHasBeenMade = true
activity?.let { activity?.let {
AlertDialog.Builder(it) MaterialAlertDialogBuilder(it)
.setTitle(R.string.dialog_title_success) .setTitle(R.string.dialog_title_success)
.setMessage(R.string.recovery_key_export_saved) .setMessage(R.string.recovery_key_export_saved)
} }

View File

@ -73,7 +73,7 @@ class KeyRequestHandler @Inject constructor(
} }
override fun onSecretShareRequest(request: IncomingSecretShareRequest): Boolean { override fun onSecretShareRequest(request: IncomingSecretShareRequest): Boolean {
// By default riotX will not prompt if the SDK has decided that the request should not be fulfilled // By default Element will not prompt if the SDK has decided that the request should not be fulfilled
Timber.v("## onSecretShareRequest() : Ignoring $request") Timber.v("## onSecretShareRequest() : Ignoring $request")
request.ignore?.run() request.ignore?.run()
return true return true

View File

@ -22,12 +22,12 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.view.View import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentOnAttachListener import androidx.fragment.app.FragmentOnAttachListener
import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
@ -98,7 +98,7 @@ class SharedSecureStorageActivity :
finish() finish()
} }
is SharedSecureStorageViewEvent.Error -> { is SharedSecureStorageViewEvent.Error -> {
AlertDialog.Builder(this) MaterialAlertDialogBuilder(this)
.setTitle(getString(R.string.dialog_title_error)) .setTitle(getString(R.string.dialog_title_error))
.setMessage(it.message) .setMessage(it.message)
.setCancelable(false) .setCancelable(false)

View File

@ -26,13 +26,13 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.commitTransaction
@ -96,7 +96,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBoot
dismiss() dismiss()
} }
is BootstrapViewEvents.ModalError -> { is BootstrapViewEvents.ModalError -> {
AlertDialog.Builder(requireActivity()) MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(event.error) .setMessage(event.error)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -121,7 +121,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetBoot
} }
private fun promptSkip() { private fun promptSkip() {
AlertDialog.Builder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.are_you_sure) .setTitle(R.string.are_you_sure)
.setMessage(R.string.bootstrap_cancel_text) .setMessage(R.string.bootstrap_cancel_text)
.setPositiveButton(R.string._continue, null) .setPositiveButton(R.string._continue, null)

View File

@ -19,8 +19,8 @@ package im.vector.app.features.crypto.recover
import android.app.Activity import android.app.Activity
import android.content.DialogInterface import android.content.DialogInterface
import android.view.KeyEvent import android.view.KeyEvent
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.databinding.DialogRecoveryKeySavedInfoBinding import im.vector.app.databinding.DialogRecoveryKeySavedInfoBinding
import me.gujun.android.span.image import me.gujun.android.span.image
@ -49,7 +49,7 @@ class KeepItSafeDialog {
} }
} }
AlertDialog.Builder(activity) MaterialAlertDialogBuilder(activity)
// .setIcon(android.R.drawable.ic_dialog_alert) // .setIcon(android.R.drawable.ic_dialog_alert)
// .setTitle(R.string.devices_delete_dialog_title) // .setTitle(R.string.devices_delete_dialog_title)
.setView(dialogLayout) .setView(dialogLayout)

View File

@ -25,18 +25,18 @@ class SupportedVerificationMethodsProvider @Inject constructor(
private val hardwareInfo: HardwareInfo private val hardwareInfo: HardwareInfo
) { ) {
/** /**
* Provide the list of supported method by RiotX, with or without the QR_CODE_SCAN, depending if a back camera * Provide the list of supported method by Element, with or without the QR_CODE_SCAN, depending if a back camera
* is available * is available
*/ */
fun provide(): List<VerificationMethod> { fun provide(): List<VerificationMethod> {
return mutableListOf( return mutableListOf(
// RiotX supports SAS verification // Element supports SAS verification
VerificationMethod.SAS, VerificationMethod.SAS,
// RiotX is able to show QR codes // Element is able to show QR codes
VerificationMethod.QR_CODE_SHOW) VerificationMethod.QR_CODE_SHOW)
.apply { .apply {
if (hardwareInfo.hasBackCamera()) { if (hardwareInfo.hasBackCamera()) {
// RiotX is able to scan QR codes, and a Camera is available // Element is able to scan QR codes, and a Camera is available
add(VerificationMethod.QR_CODE_SCAN) add(VerificationMethod.QR_CODE_SCAN)
} else { } else {
// This quite uncommon // This quite uncommon

View File

@ -23,11 +23,11 @@ import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.commitTransaction
@ -109,7 +109,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetV
)) ))
} }
is VerificationBottomSheetViewEvents.ModalError -> { is VerificationBottomSheetViewEvents.ModalError -> {
AlertDialog.Builder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.dialog_title_error)) .setTitle(getString(R.string.dialog_title_error))
.setMessage(it.errorMessage) .setMessage(it.errorMessage)
.setCancelable(false) .setCancelable(false)

View File

@ -19,7 +19,7 @@ package im.vector.app.features.crypto.verification.cancel
import androidx.core.text.toSpannable import androidx.core.text.toSpannable
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.colorizeMatchingText
@ -70,29 +70,29 @@ class VerificationCancelController @Inject constructor(
} }
} }
dividerItem { bottomSheetDividerItem {
id("sep0") id("sep0")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("cancel") id("cancel")
title(host.stringProvider.getString(R.string.skip)) title(host.stringProvider.getString(R.string.skip))
titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColor(R.color.riotx_destructive_accent)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
listener { host.listener?.onTapCancel() } listener { host.listener?.onTapCancel() }
} }
dividerItem { bottomSheetDividerItem {
id("sep1") id("sep1")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("continue") id("continue")
title(host.stringProvider.getString(R.string._continue)) title(host.stringProvider.getString(R.string._continue))
titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onTapContinue() } listener { host.listener?.onTapContinue() }
} }
} }

View File

@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.cancel
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState import im.vector.app.features.crypto.verification.VerificationBottomSheetViewState
@ -49,29 +49,29 @@ class VerificationNotMeController @Inject constructor(
notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification))) notice(host.eventHtmlRenderer.render(host.stringProvider.getString(R.string.verify_not_me_self_verification)))
} }
dividerItem { bottomSheetDividerItem {
id("sep0") id("sep0")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("skip") id("skip")
title(host.stringProvider.getString(R.string.skip)) title(host.stringProvider.getString(R.string.skip))
titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onTapSkip() } listener { host.listener?.onTapSkip() }
} }
dividerItem { bottomSheetDividerItem {
id("sep1") id("sep1")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("settings") id("settings")
title(host.stringProvider.getString(R.string.settings)) title(host.stringProvider.getString(R.string.settings))
titleColor(host.colorProvider.getColor(R.color.riotx_positive_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColor(R.color.riotx_positive_accent)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onTapSettings() } listener { host.listener?.onTapSettings() }
} }
} }

View File

@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.choose
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
@ -56,7 +56,7 @@ class VerificationChooseMethodController @Inject constructor(
data(state.qrCodeText) data(state.qrCodeText)
} }
dividerItem { bottomSheetDividerItem {
id("sep0") id("sep0")
} }
} }
@ -65,13 +65,13 @@ class VerificationChooseMethodController @Inject constructor(
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("openCamera") id("openCamera")
title(host.stringProvider.getString(R.string.verification_scan_their_code)) title(host.stringProvider.getString(R.string.verification_scan_their_code))
titleColor(host.colorProvider.getColor(R.color.riotx_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_camera) iconRes(R.drawable.ic_camera)
iconColor(host.colorProvider.getColor(R.color.riotx_accent)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.openCamera() } listener { host.listener?.openCamera() }
} }
dividerItem { bottomSheetDividerItem {
id("sep1") id("sep1")
} }
} }
@ -79,35 +79,35 @@ class VerificationChooseMethodController @Inject constructor(
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("openEmoji") id("openEmoji")
title(host.stringProvider.getString(R.string.verification_scan_emoji_title)) title(host.stringProvider.getString(R.string.verification_scan_emoji_title))
titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
subTitle(host.stringProvider.getString(R.string.verification_scan_emoji_subtitle)) subTitle(host.stringProvider.getString(R.string.verification_scan_emoji_subtitle))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.doVerifyBySas() } listener { host.listener?.doVerifyBySas() }
} }
} else if (state.sasModeAvailable) { } else if (state.sasModeAvailable) {
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("openEmoji") id("openEmoji")
title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title)) title(host.stringProvider.getString(R.string.verification_no_scan_emoji_title))
titleColor(host.colorProvider.getColor(R.color.riotx_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.doVerifyBySas() } listener { host.listener?.doVerifyBySas() }
} }
} }
if (state.isMe && state.canCrossSign) { if (state.isMe && state.canCrossSign) {
dividerItem { bottomSheetDividerItem {
id("sep_notMe") id("sep_notMe")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("wasnote") id("wasnote")
title(host.stringProvider.getString(R.string.verify_new_session_was_not_me)) title(host.stringProvider.getString(R.string.verify_new_session_was_not_me))
titleColor(host.colorProvider.getColor(R.color.riotx_destructive_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorError))
subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized)) subTitle(host.stringProvider.getString(R.string.verify_new_session_compromized))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onClickOnWasNotMe() } listener { host.listener?.onClickOnWasNotMe() }
} }
} }

View File

@ -18,7 +18,7 @@ package im.vector.app.features.crypto.verification.conclusion
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.dividerItem import im.vector.app.core.epoxy.bottomSheetDividerItem
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
@ -87,16 +87,16 @@ class VerificationConclusionController @Inject constructor(
notice(host.stringProvider.getString(R.string.verify_cancelled_notice)) notice(host.stringProvider.getString(R.string.verify_cancelled_notice))
} }
dividerItem { bottomSheetDividerItem {
id("sep0") id("sep0")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("got_it") id("got_it")
title(host.stringProvider.getString(R.string.sas_got_it)) title(host.stringProvider.getString(R.string.sas_got_it))
titleColor(host.colorProvider.getColor(R.color.riotx_accent)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColor(R.color.riotx_accent)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.colorPrimary))
listener { host.listener?.onButtonTapped() } listener { host.listener?.onButtonTapped() }
} }
} }
@ -105,16 +105,16 @@ class VerificationConclusionController @Inject constructor(
private fun bottomDone() { private fun bottomDone() {
val host = this val host = this
dividerItem { bottomSheetDividerItem {
id("sep0") id("sep0")
} }
bottomSheetVerificationActionItem { bottomSheetVerificationActionItem {
id("done") id("done")
title(host.stringProvider.getString(R.string.done)) title(host.stringProvider.getString(R.string.done))
titleColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
iconRes(R.drawable.ic_arrow_right) iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.listener?.onButtonTapped() } listener { host.listener?.onButtonTapped() }
} }
} }

Some files were not shown because too many files have changed in this diff Show More