mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 11:59:12 +03:00
Merge branch 'develop' into feature/ons/change_pin
* develop: Format source Fix / double bottomsheet effect Version** Ensure the Activity is destroyed, it seems that the intent flags are not enough now. - finish all Ensure the Activity is destroyed, it seems that the intent flags are not enough now. Remove redundant returns Prepare version 1.0.11 Fix issue when there is no display name Cleanup Fix issue with too big icons Use style instead of duplicating the whole layout file Try other asset strategy as lint not happy Convert TermsService to suspend functions Convert UploadsService to suspend functions Convert IntegrationManagerService to suspend functions update change log Home empty screen design update
This commit is contained in:
commit
ffe9a03d3e
34 changed files with 304 additions and 216 deletions
40
CHANGES.md
40
CHANGES.md
|
@ -1,4 +1,31 @@
|
|||
Changes in Element 1.0.11 (2020-XX-XX)
|
||||
Changes in Element 1.0.12 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
|
||||
Improvements 🙌:
|
||||
- Add Setting Item to Change PIN (#2462)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Double bottomsheet effect after verify with passphrase
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
SDK API changes ⚠️:
|
||||
-
|
||||
|
||||
Build 🧱:
|
||||
-
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
-
|
||||
|
||||
Changes in Element 1.0.11 (2020-11-27)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
|
@ -14,8 +41,8 @@ Improvements 🙌:
|
|||
- Handle events of type "m.room.server_acl" (#890)
|
||||
- Room creation form: add advanced section to disable federation (#1314)
|
||||
- Move "Enable Encryption" from room setting screen to room profile screen (#2394)
|
||||
- Home empty screens quick design update (#2347)
|
||||
- Improve Invite user screen (seamless search for matrix ID)
|
||||
- Add Setting Item to Change PIN (#2462)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix crash on AttachmentViewer (#2365)
|
||||
|
@ -30,14 +57,9 @@ Bugfix 🐛:
|
|||
- Update profile has no effect if user is in zero rooms
|
||||
- Fix issues with matrix.to deep linking (#2349)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354). Note: We will incrementally migrate all the SDK API in a near future.
|
||||
|
||||
Build 🧱:
|
||||
-
|
||||
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354).
|
||||
Note: We will incrementally migrate all the SDK API in a near future (#2449)
|
||||
|
||||
Test:
|
||||
- Add `allScreensTest` to cover all screens of the app
|
||||
|
|
2
fastlane/metadata/android/en-US/changelogs/40100110.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40100110.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
This new version mainly contains user interface and user experience improvements. Now you can invite friends, and create DM very fast by scanning QR codes.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.integrationmanager
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
||||
*/
|
||||
|
@ -80,19 +77,17 @@ interface IntegrationManagerService {
|
|||
/**
|
||||
* Offers to enable or disable the integration.
|
||||
* @param enable the param to change
|
||||
* @param callback the matrix callback to listen for result.
|
||||
* @return Cancelable
|
||||
*/
|
||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setIntegrationEnabled(enable: Boolean)
|
||||
|
||||
/**
|
||||
* Offers to allow or disallow a widget.
|
||||
* @param stateEventId the eventId of the state event defining the widget.
|
||||
* @param allowed the param to change
|
||||
* @param callback the matrix callback to listen for result.
|
||||
* @return Cancelable
|
||||
*/
|
||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean)
|
||||
|
||||
/**
|
||||
* Returns true if the widget is allowed, false otherwise.
|
||||
|
@ -105,7 +100,7 @@ interface IntegrationManagerService {
|
|||
* @param widgetType the widget type to check for
|
||||
* @param domain the domain to check for
|
||||
*/
|
||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean)
|
||||
|
||||
/**
|
||||
* Returns true if the widget domain is allowed, false otherwise.
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.room.uploads
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* This interface defines methods to get event with uploads (= attachments) sent to a room. It's implemented at the room level.
|
||||
*/
|
||||
|
@ -29,7 +26,5 @@ interface UploadsService {
|
|||
* @param numberOfEvents the expected number of events to retrieve. The result can contain less events.
|
||||
* @param since token to get next page, or null to get the first page
|
||||
*/
|
||||
fun getUploads(numberOfEvents: Int,
|
||||
since: String?,
|
||||
callback: MatrixCallback<GetUploadsResult>): Cancelable
|
||||
suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult
|
||||
}
|
||||
|
|
|
@ -16,22 +16,16 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.terms
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
|
||||
interface TermsService {
|
||||
enum class ServiceType {
|
||||
IntegrationManager,
|
||||
IdentityService
|
||||
}
|
||||
|
||||
fun getTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
callback: MatrixCallback<GetTermsResponse>): Cancelable
|
||||
suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse
|
||||
|
||||
fun agreeToTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?,
|
||||
callback: MatrixCallback<Unit>): Cancelable
|
||||
suspend fun agreeToTerms(serviceType: ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?)
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.integrationmanager
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
||||
|
@ -44,20 +42,20 @@ internal class DefaultIntegrationManagerService @Inject constructor(private val
|
|||
return integrationManager.isIntegrationEnabled()
|
||||
}
|
||||
|
||||
override fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setIntegrationEnabled(enable, callback)
|
||||
override suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||
integrationManager.setIntegrationEnabled(enable)
|
||||
}
|
||||
|
||||
override fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setWidgetAllowed(stateEventId, allowed, callback)
|
||||
override suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||
integrationManager.setWidgetAllowed(stateEventId, allowed)
|
||||
}
|
||||
|
||||
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||
return integrationManager.isWidgetAllowed(stateEventId)
|
||||
}
|
||||
|
||||
override fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed, callback)
|
||||
override suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||
integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed)
|
||||
}
|
||||
|
||||
override fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean {
|
||||
|
|
|
@ -20,15 +20,12 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.NoOpCancellable
|
||||
import org.matrix.android.sdk.internal.database.model.WellknownIntegrationManagerConfigEntity
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.extensions.observeNotNull
|
||||
|
@ -41,7 +38,6 @@ import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccoun
|
|||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
||||
import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -137,22 +133,17 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
return integrationProvisioningContent?.enabled ?: false
|
||||
}
|
||||
|
||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setIntegrationEnabled(enable: Boolean) {
|
||||
val isIntegrationEnabled = isIntegrationEnabled()
|
||||
if (enable == isIntegrationEnabled) {
|
||||
callback.onSuccess(Unit)
|
||||
return NoOpCancellable
|
||||
return
|
||||
}
|
||||
val integrationProvisioningContent = IntegrationProvisioningContent(enabled = enable)
|
||||
val params = UpdateUserAccountDataTask.IntegrationProvisioning(integrationProvisioningContent = integrationProvisioningContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean) {
|
||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||
val newContent = if (currentContent == null) {
|
||||
|
@ -165,11 +156,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
currentContent.copy(widgets = allowedWidgets)
|
||||
}
|
||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||
|
@ -178,7 +165,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
return currentContent?.widgets?.get(stateEventId) ?: false
|
||||
}
|
||||
|
||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean) {
|
||||
val currentAllowedWidgets = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_ALLOWED_WIDGETS)
|
||||
val currentContent = currentAllowedWidgets?.content?.toModel<AllowedWidgetsContent>()
|
||||
val newContent = if (currentContent == null) {
|
||||
|
@ -195,11 +182,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri
|
|||
currentContent.copy(native = nativeAllowedWidgets)
|
||||
}
|
||||
val params = UpdateUserAccountDataTask.AllowedWidgets(allowedWidgetsContent = newContent)
|
||||
return updateUserAccountDataTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
return updateUserAccountDataTask.execute(params)
|
||||
}
|
||||
|
||||
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String?): Boolean {
|
||||
|
|
|
@ -18,17 +18,12 @@ package org.matrix.android.sdk.internal.session.room.uploads
|
|||
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||
import org.matrix.android.sdk.api.session.room.uploads.GetUploadsResult
|
||||
import org.matrix.android.sdk.api.session.room.uploads.UploadsService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
|
||||
internal class DefaultUploadsService @AssistedInject constructor(
|
||||
@Assisted private val roomId: String,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val getUploadsTask: GetUploadsTask,
|
||||
private val cryptoService: CryptoService
|
||||
) : UploadsService {
|
||||
|
@ -38,11 +33,7 @@ internal class DefaultUploadsService @AssistedInject constructor(
|
|||
fun create(roomId: String): UploadsService
|
||||
}
|
||||
|
||||
override fun getUploads(numberOfEvents: Int, since: String?, callback: MatrixCallback<GetUploadsResult>): Cancelable {
|
||||
return getUploadsTask
|
||||
.configureWith(GetUploadsTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), numberOfEvents, since)) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
override suspend fun getUploads(numberOfEvents: Int, since: String?): GetUploadsResult {
|
||||
return getUploadsTask.execute(GetUploadsTask.Params(roomId, cryptoService.isRoomEncrypted(roomId), numberOfEvents, since))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
package org.matrix.android.sdk.internal.session.terms
|
||||
|
||||
import dagger.Lazy
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import org.matrix.android.sdk.internal.network.RetrofitFactory
|
||||
|
@ -33,8 +32,6 @@ import org.matrix.android.sdk.internal.session.sync.model.accountdata.AcceptedTe
|
|||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.AccountDataDataSource
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.launchToCallback
|
||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.internal.util.ensureTrailingSlash
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -49,13 +46,11 @@ internal class DefaultTermsService @Inject constructor(
|
|||
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
||||
private val identityRegisterTask: IdentityRegisterTask,
|
||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val taskExecutor: TaskExecutor
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers
|
||||
) : TermsService {
|
||||
override fun getTerms(serviceType: TermsService.ServiceType,
|
||||
baseUrl: String,
|
||||
callback: MatrixCallback<GetTermsResponse>): Cancelable {
|
||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
override suspend fun getTerms(serviceType: TermsService.ServiceType,
|
||||
baseUrl: String): GetTermsResponse {
|
||||
return withContext(coroutineDispatchers.main) {
|
||||
val url = buildUrl(baseUrl, serviceType)
|
||||
val termsResponse = executeRequest<TermsResponse>(null) {
|
||||
apiCall = termsAPI.getTerms("${url}terms")
|
||||
|
@ -64,12 +59,11 @@ internal class DefaultTermsService @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun agreeToTerms(serviceType: TermsService.ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?,
|
||||
callback: MatrixCallback<Unit>): Cancelable {
|
||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
override suspend fun agreeToTerms(serviceType: TermsService.ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?) {
|
||||
withContext(coroutineDispatchers.main) {
|
||||
val url = buildUrl(baseUrl, serviceType)
|
||||
val tokenToUse = token?.takeIf { it.isNotEmpty() } ?: getToken(baseUrl)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ androidExtensions {
|
|||
// Note: 2 digits max for each value
|
||||
ext.versionMajor = 1
|
||||
ext.versionMinor = 0
|
||||
ext.versionPatch = 11
|
||||
ext.versionPatch = 12
|
||||
|
||||
static def getGitTimestamp() {
|
||||
def cmd = 'git show -s --format=%ct'
|
||||
|
|
|
@ -36,6 +36,7 @@ import im.vector.app.features.crypto.recover.BootstrapMigrateBackupFragment
|
|||
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
|
||||
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
|
||||
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
|
||||
import im.vector.app.features.crypto.verification.QuadSLoadingFragment
|
||||
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
|
||||
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
|
||||
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
|
||||
|
@ -418,6 +419,11 @@ interface FragmentModule {
|
|||
@FragmentKey(VerificationCancelFragment::class)
|
||||
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(QuadSLoadingFragment::class)
|
||||
fun bindQuadSLoadingFragment(fragment: QuadSLoadingFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(VerificationNotMeFragment::class)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 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.extensions
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
|
||||
fun ConstraintLayout.updateConstraintSet(block: (ConstraintSet) -> Unit) {
|
||||
ConstraintSet().let {
|
||||
it.clone(this)
|
||||
block.invoke(it)
|
||||
it.applyTo(this)
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import android.view.View
|
|||
import android.widget.FrameLayout
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.updateConstraintSet
|
||||
import kotlinx.android.synthetic.main.view_state.view.*
|
||||
|
||||
class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
|
@ -31,7 +32,12 @@ class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
sealed class State {
|
||||
object Content : State()
|
||||
object Loading : State()
|
||||
data class Empty(val title: CharSequence? = null, val image: Drawable? = null, val message: CharSequence? = null) : State()
|
||||
data class Empty(
|
||||
val title: CharSequence? = null,
|
||||
val image: Drawable? = null,
|
||||
val isBigImage: Boolean = false,
|
||||
val message: CharSequence? = null
|
||||
) : State()
|
||||
|
||||
data class Error(val message: CharSequence? = null) : State()
|
||||
}
|
||||
|
@ -71,6 +77,9 @@ class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
is State.Loading -> Unit
|
||||
is State.Empty -> {
|
||||
emptyImageView.setImageDrawable(newState.image)
|
||||
emptyView.updateConstraintSet {
|
||||
it.constrainPercentHeight(R.id.emptyImageView, if (newState.isBigImage) 0.5f else 0.1f)
|
||||
}
|
||||
emptyMessageView.text = newState.message
|
||||
emptyTitleView.text = newState.title
|
||||
}
|
||||
|
|
|
@ -62,8 +62,8 @@ data class MainActivityArgs(
|
|||
) : Parcelable
|
||||
|
||||
/**
|
||||
* This is the entry point of RiotX
|
||||
* This Activity, when started with argument, is also doing some cleanup when user disconnects,
|
||||
* This is the entry point of Element Android
|
||||
* This Activity, when started with argument, is also doing some cleanup when user signs out,
|
||||
* clears cache, is logged out, or is soft logged out
|
||||
*/
|
||||
class MainActivity : VectorBaseActivity(), UnlockedActivity {
|
||||
|
@ -78,6 +78,8 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity {
|
|||
|
||||
intent.putExtra(EXTRA_ARGS, args)
|
||||
activity.startActivity(intent)
|
||||
// Ensure all the Activities are destroyed, it seems that the intent flags are not enough now.
|
||||
activity.finishAffinity()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 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.features.crypto.verification
|
||||
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import javax.inject.Inject
|
||||
|
||||
class QuadSLoadingFragment @Inject constructor() : VectorBaseFragment() {
|
||||
override fun getLayoutResId() = R.layout.fragment_progress
|
||||
}
|
|
@ -31,5 +31,6 @@ sealed class VerificationAction : VectorViewModelAction {
|
|||
object SkipVerification : VerificationAction()
|
||||
object VerifyFromPassphrase : VerificationAction()
|
||||
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
|
||||
object CancelledFromSsss : VerificationAction()
|
||||
object SecuredStorageHasBeenReset : VerificationAction()
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
// all have been reset, so we are verified?
|
||||
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
|
||||
}
|
||||
} else {
|
||||
viewModel.handle(VerificationAction.CancelledFromSsss)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,6 +211,10 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
return@withState
|
||||
}
|
||||
|
||||
if (state.selfVerificationMode && state.verifyingFrom4S) {
|
||||
showFragment(QuadSLoadingFragment::class, Bundle())
|
||||
return@withState
|
||||
}
|
||||
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
|
||||
showFragment(VerificationConclusionFragment::class, Bundle().apply {
|
||||
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
|
||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.app.core.extensions.exhaustive
|
|||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
@ -70,6 +71,7 @@ data class VerificationBottomSheetViewState(
|
|||
// true when we display the loading and we wait for the other (incoming request)
|
||||
val selfVerificationMode: Boolean = false,
|
||||
val verifiedFromPrivateKeys: Boolean = false,
|
||||
val verifyingFrom4S: Boolean = false,
|
||||
val isMe: Boolean = false,
|
||||
val currentDeviceCanCrossSign: Boolean = false,
|
||||
val userWantsToCancel: Boolean = false,
|
||||
|
@ -170,7 +172,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
}
|
||||
} else {
|
||||
// if the verification is already done you can't cancel anymore
|
||||
if (state.pendingRequest.invoke()?.cancelConclusion != null || state.sasTransactionState is VerificationTxState.TerminalTxState) {
|
||||
if (state.pendingRequest.invoke()?.cancelConclusion != null
|
||||
|| state.sasTransactionState is VerificationTxState.TerminalTxState
|
||||
|| state.verifyingFrom4S) {
|
||||
// you cannot cancel anymore
|
||||
} else {
|
||||
setState {
|
||||
|
@ -346,6 +350,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
||||
}
|
||||
is VerificationAction.VerifyFromPassphrase -> {
|
||||
setState { copy(verifyingFrom4S = true) }
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
||||
}
|
||||
is VerificationAction.GotResultFromSsss -> {
|
||||
|
@ -354,56 +359,73 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
VerificationAction.SecuredStorageHasBeenReset -> {
|
||||
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
|
||||
setState {
|
||||
copy(quadSHasBeenReset = true)
|
||||
copy(quadSHasBeenReset = true, verifyingFrom4S = false)
|
||||
}
|
||||
}
|
||||
Unit
|
||||
}
|
||||
VerificationAction.CancelledFromSsss -> {
|
||||
setState {
|
||||
copy(verifyingFrom4S = false)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
||||
try {
|
||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||
res?.get(MASTER_KEY_SSSS_NAME),
|
||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||
)
|
||||
if (trustResult.isVerified()) {
|
||||
// Sign this device and upload the signature
|
||||
session.sessionParams.deviceId?.let { deviceId ->
|
||||
session.cryptoService()
|
||||
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.w(failure, "Failed to sign my device after recovery")
|
||||
}
|
||||
})
|
||||
}
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||
res?.get(MASTER_KEY_SSSS_NAME),
|
||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||
)
|
||||
if (trustResult.isVerified()) {
|
||||
// Sign this device and upload the signature
|
||||
session.sessionParams.deviceId?.let { deviceId ->
|
||||
session.cryptoService()
|
||||
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.w(failure, "Failed to sign my device after recovery")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(verifiedFromPrivateKeys = true)
|
||||
}
|
||||
setState {
|
||||
copy(
|
||||
verifyingFrom4S = false,
|
||||
verifiedFromPrivateKeys = true
|
||||
)
|
||||
}
|
||||
|
||||
// try to get keybackup key
|
||||
} else {
|
||||
// POP UP something
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
||||
// try the keybackup
|
||||
tentativeRestoreBackup(res)
|
||||
} else {
|
||||
setState {
|
||||
copy(
|
||||
verifyingFrom4S = false
|
||||
)
|
||||
}
|
||||
// POP UP something
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
|
||||
}
|
||||
}
|
||||
|
||||
// try the keybackup
|
||||
tentativeRestoreBackup(res)
|
||||
Unit
|
||||
} catch (failure: Throwable) {
|
||||
setState {
|
||||
copy(
|
||||
verifyingFrom4S = false
|
||||
)
|
||||
}
|
||||
_viewEvents.post(
|
||||
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(
|
||||
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
||||
Timber.v("## Keybackup secret not restored from SSSS")
|
||||
|
|
|
@ -31,7 +31,6 @@ import kotlinx.coroutines.launch
|
|||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
|
||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import java.net.UnknownHostException
|
||||
|
@ -117,9 +116,7 @@ class SetIdentityServerViewModel @AssistedInject constructor(
|
|||
|
||||
private suspend fun checkTerms(baseUrl: String) {
|
||||
try {
|
||||
val data = awaitCallback<GetTermsResponse> {
|
||||
mxSession.getTerms(TermsService.ServiceType.IdentityService, baseUrl, it)
|
||||
}
|
||||
val data = mxSession.getTerms(TermsService.ServiceType.IdentityService, baseUrl)
|
||||
|
||||
// has all been accepted?
|
||||
val resp = data.serverResponse
|
||||
|
|
|
@ -91,7 +91,7 @@ class HomeActivityViewModel @AssistedInject constructor(
|
|||
val isVerified = it.getOrNull()?.isTrusted() ?: false
|
||||
if (!isVerified && onceTrusted) {
|
||||
// cross signing keys have been reset
|
||||
// Tigger a popup to re-verify
|
||||
// Trigger a popup to re-verify
|
||||
// Note: user can be null in case of logout
|
||||
safeActiveSession.getUser(safeActiveSession.myUserId)
|
||||
?.toMatrixItem()
|
||||
|
|
|
@ -294,28 +294,30 @@ class RoomListFragment @Inject constructor(
|
|||
RoomListDisplayMode.NOTIFICATIONS -> {
|
||||
if (hasNoRoom) {
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_catchup_welcome_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_catchup),
|
||||
getString(R.string.room_list_catchup_welcome_body)
|
||||
title = getString(R.string.room_list_catchup_welcome_title),
|
||||
image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_catchup),
|
||||
message = getString(R.string.room_list_catchup_welcome_body)
|
||||
)
|
||||
} else {
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_catchup_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_noun_party_popper),
|
||||
getString(R.string.room_list_catchup_empty_body))
|
||||
title = getString(R.string.room_list_catchup_empty_title),
|
||||
image = ContextCompat.getDrawable(requireContext(), R.drawable.ic_noun_party_popper),
|
||||
message = getString(R.string.room_list_catchup_empty_body))
|
||||
}
|
||||
}
|
||||
RoomListDisplayMode.PEOPLE ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_people_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_chat),
|
||||
getString(R.string.room_list_people_empty_body)
|
||||
title = getString(R.string.room_list_people_empty_title),
|
||||
image = ContextCompat.getDrawable(requireContext(), R.drawable.empty_state_dm),
|
||||
isBigImage = true,
|
||||
message = getString(R.string.room_list_people_empty_body)
|
||||
)
|
||||
RoomListDisplayMode.ROOMS ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_rooms_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_group),
|
||||
getString(R.string.room_list_rooms_empty_body)
|
||||
title = getString(R.string.room_list_rooms_empty_title),
|
||||
image = ContextCompat.getDrawable(requireContext(), R.drawable.empty_state_room),
|
||||
isBigImage = true,
|
||||
message = getString(R.string.room_list_rooms_empty_body)
|
||||
)
|
||||
else ->
|
||||
// Always display the content in this mode, because if the footer
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.matrix.android.sdk.api.session.Session
|
|||
import org.matrix.android.sdk.api.session.file.FileService
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||
import org.matrix.android.sdk.api.session.room.uploads.GetUploadsResult
|
||||
import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
|
@ -90,9 +89,7 @@ class RoomUploadsViewModel @AssistedInject constructor(
|
|||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = awaitCallback<GetUploadsResult> {
|
||||
room.getUploads(20, token, it)
|
||||
}
|
||||
val result = room.getUploads(20, token)
|
||||
|
||||
token = result.nextToken
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ import kotlinx.coroutines.GlobalScope
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
|
@ -214,7 +213,9 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||
it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
// Disable it while updating the state, will be re-enabled by the account data listener.
|
||||
it.isEnabled = false
|
||||
session.integrationManagerService().setIntegrationEnabled(newValue as Boolean, NoOpMatrixCallback())
|
||||
lifecycleScope.launch {
|
||||
session.integrationManagerService().setIntegrationEnabled(newValue as Boolean)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@ import im.vector.app.core.extensions.exhaustive
|
|||
import im.vector.app.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
|
||||
class ReviewTermsViewModel @AssistedInject constructor(
|
||||
|
@ -94,15 +92,12 @@ class ReviewTermsViewModel @AssistedInject constructor(
|
|||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
awaitCallback<Unit> {
|
||||
session.agreeToTerms(
|
||||
termsArgs.type,
|
||||
termsArgs.baseURL,
|
||||
agreedUrls,
|
||||
termsArgs.token,
|
||||
it
|
||||
)
|
||||
}
|
||||
session.agreeToTerms(
|
||||
termsArgs.type,
|
||||
termsArgs.baseURL,
|
||||
agreedUrls,
|
||||
termsArgs.token
|
||||
)
|
||||
_viewEvents.post(ReviewTermsViewEvents.Success)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "Failed to agree to terms")
|
||||
|
@ -122,9 +117,7 @@ class ReviewTermsViewModel @AssistedInject constructor(
|
|||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val data = awaitCallback<GetTermsResponse> {
|
||||
session.getTerms(termsArgs.type, termsArgs.baseURL, it)
|
||||
}
|
||||
val data = session.getTerms(termsArgs.type, termsArgs.baseURL)
|
||||
val terms = data.serverResponse.getLocalizedTerms(action.preferredLanguageCode).map {
|
||||
Term(it.localizedUrl ?: "",
|
||||
it.localizedName ?: "",
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.matrix.android.sdk.api.extensions.orFalse
|
|||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
|
@ -106,14 +105,11 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
|
|||
if (state.permissionData()?.isWebviewWidget.orFalse()) {
|
||||
WidgetPermissionsHelper(integrationManagerService, widgetService).changePermission(state.roomId, widgetId, false)
|
||||
} else {
|
||||
awaitCallback<Unit> {
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
false,
|
||||
it
|
||||
)
|
||||
}
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
false
|
||||
)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v("Failure revoking widget: ${state.widgetId}")
|
||||
|
@ -131,14 +127,11 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
|
|||
if (state.permissionData()?.isWebviewWidget.orFalse()) {
|
||||
WidgetPermissionsHelper(integrationManagerService, widgetService).changePermission(state.roomId, widgetId, true)
|
||||
} else {
|
||||
awaitCallback<Unit> {
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
true,
|
||||
it
|
||||
)
|
||||
}
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
true
|
||||
)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v("Failure allowing widget: ${state.widgetId}")
|
||||
|
|
|
@ -19,7 +19,6 @@ package im.vector.app.features.widgets.permissions
|
|||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.session.widgets.WidgetService
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
|
||||
class WidgetPermissionsHelper(private val integrationManagerService: IntegrationManagerService,
|
||||
private val widgetService: WidgetService) {
|
||||
|
@ -30,8 +29,6 @@ class WidgetPermissionsHelper(private val integrationManagerService: Integration
|
|||
widgetId = QueryStringValue.Equals(widgetId, QueryStringValue.Case.SENSITIVE)
|
||||
).firstOrNull()
|
||||
val eventId = widget?.event?.eventId ?: return
|
||||
awaitCallback<Unit> {
|
||||
integrationManagerService.setWidgetAllowed(eventId, allow, it)
|
||||
}
|
||||
integrationManagerService.setWidgetAllowed(eventId, allow)
|
||||
}
|
||||
}
|
||||
|
|
BIN
vector/src/main/res/drawable-nodpi/empty_state_dm.png
Normal file
BIN
vector/src/main/res/drawable-nodpi/empty_state_dm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 167 KiB |
BIN
vector/src/main/res/drawable-nodpi/empty_state_room.png
Normal file
BIN
vector/src/main/res/drawable-nodpi/empty_state_room.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 KiB |
14
vector/src/main/res/layout/fragment_progress.xml
Normal file
14
vector/src/main/res/layout/fragment_progress.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
||||
android:indeterminate="true" />
|
||||
|
||||
</RelativeLayout>
|
|
@ -92,14 +92,14 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="300dp">
|
||||
android:minWidth="300dp"
|
||||
android:paddingTop="40dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/showUserCodeCardNameText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/layout_horizontal_margin">
|
||||
android:padding="@dimen/layout_horizontal_margin"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorMessageView"
|
||||
|
@ -32,7 +34,6 @@
|
|||
android:textSize="16sp"
|
||||
tools:text="Une erreur est survenue" />
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/errorRetryView"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -44,7 +45,6 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/emptyView"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -53,47 +53,56 @@
|
|||
android:orientation="vertical"
|
||||
android:padding="@dimen/layout_horizontal_margin">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/emptyImageView"
|
||||
style="@style/VectorEmptyImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:maxHeight="350dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/emptyTitleView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:layout_constraintHeight_percent="0.5"
|
||||
tools:src="@drawable/ic_search_no_results" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emptyTitleView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="49dp"
|
||||
android:gravity="center"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/emptyImageView"
|
||||
app:layout_constraintBottom_toTopOf="@id/emptyMessageView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@string/room_list_catchup_empty_title" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/emptyImageView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_noun_party_popper"
|
||||
app:tint="?riotx_text_primary"
|
||||
tools:ignore="MissingPrefix" />
|
||||
app:layout_constraintTop_toBottomOf="@id/emptyImageView"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="@string/room_list_people_empty_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emptyMessageView"
|
||||
android:layout_width="220dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="49dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/emptyImageView"
|
||||
tools:text="@string/room_list_catchup_empty_body" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/emptyTitleView"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="@string/room_list_people_empty_body" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
8
vector/src/main/res/values-land/styles.xml
Normal file
8
vector/src/main/res/values-land/styles.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="VectorEmptyImageView">
|
||||
<item name="android:visibility">gone</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -1644,9 +1644,9 @@
|
|||
<string name="room_list_catchup_welcome_title">Welcome home!</string>
|
||||
<string name="room_list_catchup_welcome_body">Catch up on unread messages here</string>
|
||||
<string name="room_list_people_empty_title">Conversations</string>
|
||||
<string name="room_list_people_empty_body">Your direct message conversations will be displayed here</string>
|
||||
<string name="room_list_people_empty_body">Your direct message conversations will be displayed here. Tap the + bottom right to start some.</string>
|
||||
<string name="room_list_rooms_empty_title">Rooms</string>
|
||||
<string name="room_list_rooms_empty_body">Your rooms will be displayed here</string>
|
||||
<string name="room_list_rooms_empty_body">Your rooms will be displayed here. Tap the + bottom right to find existing ones or start some of your own.</string>
|
||||
|
||||
<string name="title_activity_emoji_reaction_picker">Reactions</string>
|
||||
<string name="reactions_agree">Agree</string>
|
||||
|
|
|
@ -3,4 +3,8 @@
|
|||
|
||||
<style name="Vector.PopupMenu" parent="Vector.PopupMenuBase" />
|
||||
|
||||
<style name="VectorEmptyImageView">
|
||||
<item name="android:visibility">visible</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
Loading…
Reference in a new issue