Apache License
diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
index e3a84f95de..fdd6e3c2ba 100644
--- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
@@ -46,6 +46,7 @@ import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.SharedPrefPinCodeStore
import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
+import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.SharedPreferencesUiStateRepository
import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.CoroutineScope
@@ -113,10 +114,13 @@ object VectorStaticModule {
}
@Provides
- fun providesMatrixConfiguration(vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration {
+ fun providesMatrixConfiguration(
+ vectorPreferences: VectorPreferences,
+ vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration {
return MatrixConfiguration(
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider,
+ threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(),
presenceSyncEnabled = BuildConfig.PRESENCE_SYNC_ENABLED
)
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Exhaustive.kt b/vector/src/main/java/im/vector/app/core/extensions/Exhaustive.kt
deleted file mode 100644
index 158ea84f0c..0000000000
--- a/vector/src/main/java/im/vector/app/core/extensions/Exhaustive.kt
+++ /dev/null
@@ -1,20 +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.extensions
-
-// Trick to ensure that when block is exhaustive
-val T.exhaustive: T get() = this
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
index 2c161feb37..4796022856 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
@@ -54,7 +54,6 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.dialogs.DialogLocker
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.observeNotNull
import im.vector.app.core.extensions.registerStartForActivityResult
@@ -267,7 +266,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver
is GlobalError.CertificateError ->
handleCertificateError(globalError)
GlobalError.ExpiredAccount -> Unit // TODO Handle account expiration
- }.exhaustive
+ }
}
private fun handleCertificateError(certificateError: GlobalError.CertificateError) {
diff --git a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
index 1a7a79ed8c..78266cf5ee 100644
--- a/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/PushRulePreference.kt
@@ -83,6 +83,7 @@ class PushRulePreference : VectorPreference {
NotificationIndex.NOISY -> {
radioGroup?.check(R.id.bingPreferenceRadioBingRuleNoisy)
}
+ null -> Unit
}
radioGroup?.setOnCheckedChangeListener { _, checkedId ->
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
index 94c1ab6576..58a5666e94 100755
--- a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
@@ -77,13 +77,10 @@ class KeysBackupBanner @JvmOverloads constructor(
override fun onClick(v: View?) {
when (state) {
- is State.Setup -> {
- delegate?.setupKeysBackup()
- }
+ is State.Setup -> delegate?.setupKeysBackup()
is State.Update,
- is State.Recover -> {
- delegate?.recoverKeysBackup()
- }
+ is State.Recover -> delegate?.recoverKeysBackup()
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
index 1615e77902..5190bb21a8 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
@@ -27,7 +27,6 @@ import androidx.core.text.italic
import im.vector.app.R
import im.vector.app.core.epoxy.onClick
import im.vector.app.core.error.ResourceLimitErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewNotificationAreaBinding
import im.vector.app.features.themes.ThemeUtils
@@ -77,7 +76,7 @@ class NotificationAreaView @JvmOverloads constructor(
is State.UnsupportedAlgorithm -> renderUnsupportedAlgorithm(newState)
is State.Tombstone -> renderTombstone()
is State.ResourceLimitExceededError -> renderResourceLimitExceededError(newState)
- }.exhaustive
+ }
}
// PRIVATE METHODS ****************************************************************************************************************************************
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt
index 301f8afdc9..82675e8c11 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt
@@ -49,6 +49,7 @@ class PresenceStateImageView @JvmOverloads constructor(
setImageResource(R.drawable.ic_presence_offline)
contentDescription = context.getString(R.string.a11y_presence_offline)
}
+ null -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
index ac0b4408b2..713c177099 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
@@ -40,21 +40,21 @@ class ShieldImageView @JvmOverloads constructor(
isVisible = roomEncryptionTrustLevel != null
when (roomEncryptionTrustLevel) {
- RoomEncryptionTrustLevel.Default -> {
+ RoomEncryptionTrustLevel.Default -> {
contentDescription = context.getString(R.string.a11y_trust_level_default)
setImageResource(
if (borderLess) R.drawable.ic_shield_black_no_border
else R.drawable.ic_shield_black
)
}
- RoomEncryptionTrustLevel.Warning -> {
+ RoomEncryptionTrustLevel.Warning -> {
contentDescription = context.getString(R.string.a11y_trust_level_warning)
setImageResource(
if (borderLess) R.drawable.ic_shield_warning_no_border
else R.drawable.ic_shield_warning
)
}
- RoomEncryptionTrustLevel.Trusted -> {
+ RoomEncryptionTrustLevel.Trusted -> {
contentDescription = context.getString(R.string.a11y_trust_level_trusted)
setImageResource(
if (borderLess) R.drawable.ic_shield_trusted_no_border
@@ -65,6 +65,7 @@ class ShieldImageView @JvmOverloads constructor(
contentDescription = context.getString(R.string.a11y_trust_level_trusted)
setImageResource(R.drawable.ic_warning_badge)
}
+ null -> Unit
}
}
}
@@ -72,9 +73,9 @@ class ShieldImageView @JvmOverloads constructor(
@DrawableRes
fun RoomEncryptionTrustLevel.toDrawableRes(): Int {
return when (this) {
- RoomEncryptionTrustLevel.Default -> R.drawable.ic_shield_black
- RoomEncryptionTrustLevel.Warning -> R.drawable.ic_shield_warning
- RoomEncryptionTrustLevel.Trusted -> R.drawable.ic_shield_trusted
+ RoomEncryptionTrustLevel.Default -> R.drawable.ic_shield_black
+ RoomEncryptionTrustLevel.Warning -> R.drawable.ic_shield_warning
+ RoomEncryptionTrustLevel.Trusted -> R.drawable.ic_shield_trusted
RoomEncryptionTrustLevel.E2EWithUnsupportedAlgorithm -> R.drawable.ic_warning_badge
}
}
diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt
index 33b735551c..42bd2318b3 100644
--- a/vector/src/main/java/im/vector/app/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt
@@ -241,7 +241,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
// We have a session.
// Check it can be opened
if (sessionHolder.getActiveSession().isOpenable) {
- HomeActivity.newIntent(this)
+ HomeActivity.newIntent(this, existingSession = true)
} else {
// The token is still invalid
navigator.softLogout(this)
diff --git a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsConsentViewModel.kt b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsConsentViewModel.kt
index 2c7a8ac9bc..a570b31452 100644
--- a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsConsentViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsConsentViewModel.kt
@@ -22,7 +22,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.VectorAnalytics
import kotlinx.coroutines.launch
@@ -55,7 +54,7 @@ class AnalyticsConsentViewModel @AssistedInject constructor(
override fun handle(action: AnalyticsConsentViewActions) {
when (action) {
is AnalyticsConsentViewActions.SetUserConsent -> handleSetUserConsent(action)
- }.exhaustive
+ }
}
private fun handleSetUserConsent(action: AnalyticsConsentViewActions.SetUserConsent) {
diff --git a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInActivity.kt b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInActivity.kt
index c84031d2fd..c11cf582d3 100644
--- a/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/analytics/ui/consent/AnalyticsOptInActivity.kt
@@ -19,7 +19,6 @@ package im.vector.app.features.analytics.ui.consent
import com.airbnb.mvrx.viewModel
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.addFragment
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.ScreenOrientationLocker
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
@@ -48,7 +47,7 @@ class AnalyticsOptInActivity : VectorBaseActivity() {
viewModel.observeViewEvents {
when (it) {
AnalyticsOptInViewEvents.OnDataSaved -> finish()
- }.exhaustive
+ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
index 0a0e700ce9..3e9d72e98b 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
@@ -17,7 +17,6 @@
package im.vector.app.features.attachments.preview
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState) :
@@ -28,7 +27,7 @@ class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState) :
is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action)
is AttachmentsPreviewAction.UpdatePathOfCurrentAttachment -> handleUpdatePathOfCurrentAttachment(action)
AttachmentsPreviewAction.RemoveCurrentAttachment -> handleRemoveCurrentAttachment()
- }.exhaustive
+ }
}
private fun handleRemoveCurrentAttachment() = withState {
diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt
index 8d30c4d5c5..b3fc36e5bc 100644
--- a/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt
+++ b/vector/src/main/java/im/vector/app/features/call/CallControlsView.kt
@@ -111,6 +111,7 @@ class CallControlsView @JvmOverloads constructor(
views.ringingControls.isVisible = false
views.connectedControls.isVisible = false
}
+ null -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index 23c7b79914..e9d16ee710 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -525,8 +525,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
navigator.openCallTransfer(this, callTransferActivityResultLauncher, callId)
}
is VectorCallViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure))
- null -> {
- }
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
index a26eec04f3..449a740cf3 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
@@ -26,7 +26,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.call.audio.CallAudioManager
import im.vector.app.features.call.dialpad.DialPadLookup
@@ -343,7 +342,7 @@ class VectorCallViewModel @AssistedInject constructor(
setState { VectorCallViewState(action.callArgs) }
setupCallWithCurrentState()
}
- }.exhaustive
+ }
}
private fun handleCallTransfer() {
@@ -358,7 +357,7 @@ class VectorCallViewModel @AssistedInject constructor(
when (result) {
is CallTransferResult.ConnectWithUserId -> connectWithUserId(result)
is CallTransferResult.ConnectWithPhoneNumber -> connectWithPhoneNumber(result)
- }.exhaustive
+ }
}
private fun connectWithUserId(result: CallTransferResult.ConnectWithUserId) {
diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
index d04bebfd1b..f0b7b75afb 100644
--- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
@@ -27,7 +27,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
@@ -103,7 +102,7 @@ class JitsiCallViewModel @AssistedInject constructor(
when (action) {
is JitsiCallViewActions.SwitchTo -> handleSwitchTo(action)
JitsiCallViewActions.OnConferenceLeft -> handleOnConferenceLeft()
- }.exhaustive
+ }
}
private fun handleSwitchTo(action: JitsiCallViewActions.SwitchTo) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
index a668f66f30..5a12337e4f 100644
--- a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt
@@ -35,7 +35,6 @@ import com.facebook.react.modules.core.PermissionListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityJitsiBinding
import kotlinx.parcelize.Parcelize
@@ -79,7 +78,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee
JitsiCallViewEvents.FailJoiningConference -> handleFailJoining()
JitsiCallViewEvents.Finish -> finish()
JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
- }.exhaustive
+ }
}
lifecycle.addObserver(ConferenceEventObserver(this, this::onBroadcastEvent))
}
diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
index d8eede6a55..b10353be13 100644
--- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
@@ -26,7 +26,6 @@ import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityCallTransferBinding
import kotlinx.parcelize.Parcelize
@@ -57,7 +56,7 @@ class CallTransferActivity : VectorBaseActivity() {
callTransferViewModel.observeViewEvents {
when (it) {
is CallTransferViewEvents.Complete -> handleComplete()
- }.exhaustive
+ }
}
sectionsPagerAdapter = CallTransferPagerAdapter(this)
diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
index ebd0089736..7425e0ae8a 100644
--- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookFragment.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.showIdentityServerConsentDialog
@@ -73,7 +72,7 @@ class ContactsBookFragment @Inject constructor(
when (it) {
is ContactsBookViewEvents.Failure -> showFailure(it.throwable)
is ContactsBookViewEvents.OnPoliciesRetrieved -> showConsentDialog(it)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt
index 5678668b25..d016558764 100644
--- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewModel.kt
@@ -27,7 +27,6 @@ import im.vector.app.core.contacts.ContactsDataSource
import im.vector.app.core.contacts.MappedContact
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.discovery.fetchIdentityServerWithTerms
@@ -165,7 +164,7 @@ class ContactsBookViewModel @AssistedInject constructor(
is ContactsBookAction.OnlyBoundContacts -> handleOnlyBoundContacts(action)
ContactsBookAction.UserConsentGranted -> handleUserConsentGranted()
ContactsBookAction.UserConsentRequest -> handleUserConsentRequest()
- }.exhaustive
+ }
}
private fun handleUserConsentRequest() {
diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
index 9df4f52d0f..0d36c7c7cc 100644
--- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt
@@ -28,6 +28,7 @@ import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.viewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
@@ -35,7 +36,6 @@ import im.vector.app.R
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.utils.PERMISSIONS_FOR_MEMBERS_SEARCH
@@ -84,7 +84,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
is UserListSharedAction.OnMenuItemSelected -> onMenuItemSelected(action)
UserListSharedAction.OpenPhoneBook -> openPhoneBook()
UserListSharedAction.AddByQrCode -> openAddByQrCode()
- }.exhaustive
+ }
}
.launchIn(lifecycleScope)
if (isFirstCreation()) {
@@ -111,7 +111,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
Toast.makeText(this, R.string.cannot_dm_self, Toast.LENGTH_SHORT).show()
finish()
}
- }.exhaustive
+ }
}
qrViewModel.observeViewEvents {
@@ -124,7 +124,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
finish()
}
else -> Unit
- }.exhaustive
+ }
}
}
@@ -167,6 +167,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
private fun renderCreateAndInviteState(state: Async) {
when (state) {
+ Uninitialized,
is Loading -> renderCreationLoading()
is Success -> renderCreationSuccess(state())
is Fail -> renderCreationFailure(state.error)
diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt
index 9dd3ef6a9b..d3011496d2 100644
--- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomViewModel.kt
@@ -24,7 +24,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.raw.wellknown.getElementWellknown
@@ -56,7 +55,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
when (action) {
is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.selections)
is CreateDirectRoomAction.QrScannedAction -> onCodeParsed(action)
- }.exhaustive
+ }
}
private fun onCodeParsed(action: CreateDirectRoomAction.QrScannedAction) {
@@ -108,7 +107,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
when (it) {
is PendingSelection.UserPendingSelection -> invitedUserIds.add(it.user.userId)
is PendingSelection.ThreePidPendingSelection -> invite3pids.add(it.threePid)
- }.exhaustive
+ }
}
setDirectMessage()
enableEncryptionIfInvitedUsersSupportIt = adminE2EByDefault
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
index 577572ef14..3c922e6309 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
@@ -140,6 +140,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(
isBackupAlreadySetup = true
}
+ null -> Unit
}
if (isBackupAlreadySetup) {
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt
index b317ac95ad..0a105064d5 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt
@@ -116,12 +116,13 @@ class SharedSecureStorageActivity :
is SharedSecureStorageViewEvent.FinishSuccess -> {
val dataResult = Intent()
dataResult.putExtra(EXTRA_DATA_RESULT, it.cypherResult)
- setResult(Activity.RESULT_OK, dataResult)
+ setResult(RESULT_OK, dataResult)
finish()
}
is SharedSecureStorageViewEvent.ShowResetBottomSheet -> {
navigator.open4SSetup(this, SetupMode.HARD_RESET)
}
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
index 8994ad901b..d324a52242 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
@@ -29,7 +29,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider
@@ -142,7 +141,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
SharedSecureStorageAction.Back -> handleBack()
SharedSecureStorageAction.ForgotResetAll -> handleResetAll()
SharedSecureStorageAction.DoResetAll -> handleDoResetAll()
- }.exhaustive
+ }
}
private fun handleDoResetAll() {
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt
index 8e7f11f0f5..fd660367ae 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStorageKeyFragment.kt
@@ -77,6 +77,7 @@ class SharedSecuredStorageKeyFragment @Inject constructor() : VectorBaseFragment
is SharedSecureStorageViewEvent.KeyInlineError -> {
views.ssssKeyEnterTil.error = it.message
}
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt
index 70c1003773..41507f2722 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecuredStoragePassphraseFragment.kt
@@ -86,6 +86,7 @@ class SharedSecuredStoragePassphraseFragment @Inject constructor(
is SharedSecureStorageViewEvent.InlineError -> {
views.ssssPassphraseEnterTil.error = it.message
}
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
index 8448422a56..ac7662ca59 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
@@ -36,7 +36,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.commitTransaction
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.toMvRxBundle
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
@@ -209,7 +208,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment Unit
}
return@withState
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
index 45f7f56957..2495ae4ea5 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
@@ -28,7 +28,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-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
@@ -365,7 +364,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
copy(verifyingFrom4S = false)
}
}
- }.exhaustive
+ }
}
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt
index 6f213adb7e..aec28f898e 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/emoji/VerificationEmojiCodeViewModel.kt
@@ -139,6 +139,7 @@ class VerificationEmojiCodeViewModel @AssistedInject constructor(
)
}
}
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
index 90997830a0..781677433b 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt
@@ -18,6 +18,7 @@ package im.vector.app.features.crypto.verification.request
import androidx.core.text.toSpannable
import com.airbnb.epoxy.EpoxyController
+import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
@@ -153,6 +154,7 @@ class VerificationRequestController @Inject constructor(
}
}
}
+ is Fail -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
index 57d3ccc16b..f1f6142fa2 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt
@@ -34,7 +34,6 @@ import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.SimpleFragmentActivity
import im.vector.app.core.resources.ColorProvider
@@ -79,7 +78,7 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac
Unit
}
is DevToolsViewEvents.ShowSnackMessage -> showSnackbar(it.message)
- }.exhaustive
+ }
}
supportFragmentManager.addOnBackStackChangedListener(this)
}
diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
index 551b72dd82..b338f367e3 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt
@@ -50,6 +50,7 @@ class DiscoverySettingsController @Inject constructor(
override fun buildModels(data: DiscoverySettingsState) {
when (data.identityServer) {
+ Uninitialized,
is Loading -> {
loadingItem {
id("identityServerLoading")
@@ -209,18 +210,19 @@ class DiscoverySettingsController @Inject constructor(
titleResId(R.string.settings_discovery_emails_title)
}
when (emails) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("emailsLoading")
}
}
- is Fail -> {
+ is Fail -> {
settingsInfoItem {
id("emailsError")
helperText(emails.error.message)
}
}
- is Success -> {
+ is Success -> {
if (emails().isEmpty()) {
settingsInfoItem {
id("emailsEmpty")
@@ -277,18 +279,19 @@ class DiscoverySettingsController @Inject constructor(
}
when (msisdns) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("msisdnLoading")
}
}
- is Fail -> {
+ is Fail -> {
settingsInfoItem {
id("msisdnListError")
helperText(msisdns.error.message)
}
}
- is Success -> {
+ is Success -> {
if (msisdns().isEmpty()) {
settingsInfoItem {
id("no_msisdn")
@@ -353,6 +356,7 @@ class DiscoverySettingsController @Inject constructor(
colorProvider(host.colorProvider)
stringProvider(host.stringProvider)
when (pidInfo.isShared) {
+ Uninitialized,
is Loading -> {
buttonIndeterminate(true)
}
@@ -384,6 +388,7 @@ class DiscoverySettingsController @Inject constructor(
else -> iconMode(IconMode.NONE)
}
}
+ null -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
index 523e8cb9bb..2de03f296e 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt
@@ -28,7 +28,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
@@ -70,7 +69,7 @@ class DiscoverySettingsFragment @Inject constructor(
when (it) {
is DiscoverySharedViewModelAction.ChangeIdentityServer ->
viewModel.handle(DiscoverySettingsAction.ChangeIdentityServer(it.newUrl))
- }.exhaustive
+ }
}
viewModel.observeViewEvents {
@@ -78,7 +77,7 @@ class DiscoverySettingsFragment @Inject constructor(
is DiscoverySettingsViewEvents.Failure -> {
displayErrorDialog(it.throwable)
}
- }.exhaustive
+ }
}
if (discoveryArgs.expandIdentityPolicies) {
viewModel.handle(DiscoverySettingsAction.SetPoliciesExpandState(expanded = true))
diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt
index 19f233fe98..8c1caaf67a 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt
@@ -27,7 +27,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.flow.launchIn
@@ -113,7 +112,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
is DiscoverySettingsAction.FinalizeBind3pid -> finalizeBind3pid(action, true)
is DiscoverySettingsAction.SubmitMsisdnToken -> submitMsisdnToken(action)
is DiscoverySettingsAction.CancelBinding -> cancelBinding(action)
- }.exhaustive
+ }
}
private fun handleUpdateUserConsent(action: DiscoverySettingsAction.UpdateUserConsent) {
@@ -235,7 +234,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
when (action.threePid) {
is ThreePid.Email -> revokeEmail(action.threePid)
is ThreePid.Msisdn -> revokeMsisdn(action.threePid)
- }.exhaustive
+ }
}
private fun revokeEmail(threePid: ThreePid.Email) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
index 527d28dfad..29a44a1d8a 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/SettingsTextButtonSingleLineItem.kt
@@ -34,7 +34,6 @@ import im.vector.app.core.epoxy.attributes.ButtonStyle
import im.vector.app.core.epoxy.attributes.ButtonType
import im.vector.app.core.epoxy.attributes.IconMode
import im.vector.app.core.epoxy.onClick
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
@@ -122,7 +121,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder {
holder.mainButton.setTextColor(colorProvider.getColorFromAttribute(R.attr.colorError))
}
- }.exhaustive
+ }
holder.mainButton.onClick(buttonClickListener)
}
ButtonType.SWITCH -> {
@@ -133,7 +132,7 @@ abstract class SettingsTextButtonSingleLineItem : EpoxyModelWithHolder useDefault()
is SetIdentityServerAction.UseCustomIdentityServer -> usedCustomIdentityServerUrl(action)
- }.exhaustive
+ }
}
private fun useDefault() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
index 964fb6f365..009edcc69e 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
@@ -38,7 +38,6 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.AppStateHandler
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.replaceFragment
@@ -90,6 +89,7 @@ import javax.inject.Inject
data class HomeActivityArgs(
val clearNotification: Boolean,
val accountCreation: Boolean,
+ val hasExistingSession: Boolean = false,
val inviteNotificationRoomId: String? = null
) : Parcelable
@@ -106,6 +106,7 @@ class HomeActivity :
@Suppress("UNUSED")
private val analyticsAccountDataViewModel: AnalyticsAccountDataViewModel by viewModel()
+
@Suppress("UNUSED")
private val userColorAccountDataViewModel: UserColorAccountDataViewModel by viewModel()
@@ -231,7 +232,7 @@ class HomeActivity :
HomeActivitySharedAction.SendSpaceFeedBack -> {
bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
}
- }.exhaustive
+ }
}
.launchIn(lifecycleScope)
@@ -253,7 +254,9 @@ class HomeActivity :
HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush()
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
HomeActivityViewEvents.ShowAnalyticsOptIn -> handleShowAnalyticsOptIn()
- }.exhaustive
+ HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration()
+ is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession)
+ }
}
homeActivityViewModel.onEach { renderState(it) }
@@ -269,6 +272,48 @@ class HomeActivity :
navigator.openAnalyticsOptIn(this)
}
+ /**
+ * Migrating from old threads io.element.thread to new m.thread needs an initial sync to
+ * sync and display existing messages appropriately
+ */
+ private fun migrateThreadsIfNeeded(checkSession: Boolean) {
+ if (checkSession) {
+ // We should check session to ensure we will only clear cache if needed
+ val args = intent.getParcelableExtra(Mavericks.KEY_ARG)
+ if (args?.hasExistingSession == true) {
+ // existingSession --> Will be true only if we came from an existing active session
+ Timber.i("----> Migrating threads from an existing session..")
+ handleThreadsMigration()
+ } else {
+ // We came from a new session and not an existing one,
+ // so there is no need to migrate threads while an initial synced performed
+ Timber.i("----> No thread migration needed, we are ok")
+ vectorPreferences.setShouldMigrateThreads(shouldMigrate = false)
+ }
+ } else {
+ // Proceed with migration
+ handleThreadsMigration()
+ }
+ }
+
+ /**
+ * Clear cache and restart to invoke an initial sync for threads migration
+ */
+ private fun handleThreadsMigration() {
+ Timber.i("----> Threads Migration detected, clearing cache and sync...")
+ vectorPreferences.setShouldMigrateThreads(shouldMigrate = false)
+ MainActivity.restartApp(this, MainActivityArgs(clearCache = true))
+ }
+
+ private fun handleNotifyUserForThreadsMigration() {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(R.string.threads_notice_migration_title)
+ .setMessage(R.string.threads_notice_migration_message)
+ .setCancelable(true)
+ .setPositiveButton(R.string.sas_got_it) { _, _ -> }
+ .show()
+ }
+
private fun handleIntent(intent: Intent?) {
intent?.dataString?.let { deepLink ->
val resolvedLink = when {
@@ -329,7 +374,7 @@ class HomeActivity :
// Idle or Incremental sync status
views.waitingView.root.isVisible = false
}
- }.exhaustive
+ }
}
private fun handleAskPasswordToInitCrossSigning(events: HomeActivityViewEvents.AskPasswordToInitCrossSigning) {
@@ -546,11 +591,13 @@ class HomeActivity :
fun newIntent(context: Context,
clearNotification: Boolean = false,
accountCreation: Boolean = false,
+ existingSession: Boolean = false,
inviteNotificationRoomId: String? = null
): Intent {
val args = HomeActivityArgs(
clearNotification = clearNotification,
accountCreation = accountCreation,
+ hasExistingSession = existingSession,
inviteNotificationRoomId = inviteNotificationRoomId
)
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
index adc44a57bd..5efd49a579 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt
@@ -25,4 +25,6 @@ sealed interface HomeActivityViewEvents : VectorViewEvents {
data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents
object PromptToEnableSessionPush : HomeActivityViewEvents
object ShowAnalyticsOptIn : HomeActivityViewEvents
+ object NotifyUserForThreadsMigration : HomeActivityViewEvents
+ data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents
}
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
index 35c112b63a..87de0a32e3 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
@@ -25,7 +25,6 @@ import im.vector.app.config.analyticsConfig
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.store.AnalyticsStore
import im.vector.app.features.login.ReAuthHelper
@@ -51,6 +50,7 @@ import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.flow.flow
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
+import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.util.awaitCallback
import timber.log.Timber
import kotlin.coroutines.Continuation
@@ -62,6 +62,7 @@ class HomeActivityViewModel @AssistedInject constructor(
private val activeSessionHolder: ActiveSessionHolder,
private val reAuthHelper: ReAuthHelper,
private val analyticsStore: AnalyticsStore,
+ private val lightweightSettingsStorage: LightweightSettingsStorage,
private val vectorPreferences: VectorPreferences
) : VectorViewModel(initialState) {
@@ -84,6 +85,7 @@ class HomeActivityViewModel @AssistedInject constructor(
checkSessionPushIsOn()
observeCrossSigningReset()
observeAnalytics()
+ initThreadsMigration()
}
private fun observeAnalytics() {
@@ -130,6 +132,46 @@ class HomeActivityViewModel @AssistedInject constructor(
.launchIn(viewModelScope)
}
+ /**
+ * Handle threads migration. The migration includes:
+ * - Notify users that had io.element.thread enabled from labs
+ * - Re-Enable m.thread to those users (that they had enabled labs threads)
+ * - Handle migration when threads are enabled by default
+ */
+ private fun initThreadsMigration() {
+ // When we would like to enable threads for all users
+// if(vectorPreferences.shouldMigrateThreads()) {
+// vectorPreferences.setThreadMessagesEnabled()
+// lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
+// }
+
+ when {
+ // Notify users
+ vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled() -> {
+ Timber.i("----> Notify users about threads")
+ // Notify the user if needed that we migrated to support m.thread
+ // instead of io.element.thread so old thread messages will be displayed as normal timeline messages
+ _viewEvents.post(HomeActivityViewEvents.NotifyUserForThreadsMigration)
+ vectorPreferences.userNotifiedAboutThreads()
+ }
+ // Migrate users with enabled lab settings
+ vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.shouldMigrateThreads() -> {
+ Timber.i("----> Migrate threads with enabled labs")
+ // If user had io.element.thread enabled then enable the new thread support,
+ // clear cache to sync messages appropriately
+ vectorPreferences.setThreadMessagesEnabled()
+ lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
+ // Clear Cache
+ _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = false))
+ }
+ // Enable all users
+ vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled() -> {
+ Timber.i("----> Try to migrate threads")
+ _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true))
+ }
+ }
+ }
+
private fun observeInitialSync() {
val session = activeSessionHolder.getSafeActiveSession() ?: return
@@ -263,6 +305,6 @@ class HomeActivityViewModel @AssistedInject constructor(
HomeActivityViewActions.ViewStarted -> {
initialize()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
index e812942996..01d91f3edc 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
@@ -273,6 +273,7 @@ class HomeDetailViewModel @AssistedInject constructor(
)
}
}
+ null -> Unit
}
}
.launchIn(viewModelScope)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
index 1c06d0ef58..c6d0b45a04 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
@@ -72,7 +72,6 @@ import im.vector.app.core.dialogs.ConfirmationDialogBuilder
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper
import im.vector.app.core.epoxy.LayoutManagerStateRestorer
import im.vector.app.core.extensions.cleanup
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.setTextOrHide
@@ -177,6 +176,7 @@ import im.vector.app.features.html.PillsPostProcessor
import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.location.toLocationData
+import im.vector.app.features.media.AttachmentData
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.notifications.NotificationDrawerManager
@@ -445,7 +445,7 @@ class TimelineFragment @Inject constructor(
}
showErrorInSnackbar(it.throwable)
}
- }.exhaustive
+ }
}
timelineViewModel.observeViewEvents {
@@ -482,7 +482,7 @@ class TimelineFragment @Inject constructor(
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
RoomDetailViewEvents.RoomReplacementStarted -> handleRoomReplacement()
- }.exhaustive
+ }
}
if (savedInstanceState == null) {
@@ -783,6 +783,18 @@ class TimelineFragment @Inject constructor(
updateRecordingUiState(RecordingUiState.Draft)
}
+ override fun onVoiceWaveformTouchedUp(percentage: Float, duration: Int) {
+ messageComposerViewModel.handle(
+ MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
+ )
+ }
+
+ override fun onVoiceWaveformMoved(percentage: Float, duration: Int) {
+ messageComposerViewModel.handle(
+ MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
+ )
+ }
+
private fun updateRecordingUiState(state: RecordingUiState) {
messageComposerViewModel.handle(
MessageComposerAction.OnVoiceRecordingUiStateChanged(state))
@@ -874,7 +886,7 @@ class TimelineFragment @Inject constructor(
onContentAttachmentsReady(sharedData.attachmentData)
}
null -> Timber.v("No share data to process")
- }.exhaustive
+ }
}
private fun handleSpaceShare() {
@@ -1240,7 +1252,7 @@ class TimelineFragment @Inject constructor(
insertUserDisplayNameInTextEditor(roomDetailPendingAction.userId)
is RoomDetailPendingAction.OpenRoom ->
handleOpenRoom(RoomDetailViewEvents.OpenRoom(roomDetailPendingAction.roomId, roomDetailPendingAction.closeCurrentRoom))
- }.exhaustive
+ }
}
override fun onPause() {
@@ -1612,11 +1624,10 @@ class TimelineFragment @Inject constructor(
views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName
avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView)
- views.includeRoomToolbar.roomToolbarDecorationImageView.render(roomSummary.roomEncryptionTrustLevel)
- views.includeRoomToolbar.roomToolbarPresenceImageView.render(
- roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled,
- roomSummary.directUserPresence
- )
+ val showPresence = roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled
+ views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence)
+ val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield
+ shieldView.render(roomSummary.roomEncryptionTrustLevel)
views.includeRoomToolbar.roomToolbarPublicImageView.isVisible = roomSummary.isPublic && !roomSummary.isDirect
}
} else {
@@ -1658,7 +1669,7 @@ class TimelineFragment @Inject constructor(
is MessageComposerViewEvents.SlashCommandNotSupportedInThreads -> {
displayCommandError(getString(R.string.command_not_supported_in_threads, sendMessageResult.command.command))
}
- } // .exhaustive
+ } //
lockSendButton = false
}
@@ -1782,6 +1793,7 @@ class TimelineFragment @Inject constructor(
transactionId = data.transactionId,
).show(parentFragmentManager, "REQ")
}
+ else -> Unit
}
}
@@ -1871,12 +1883,16 @@ class TimelineFragment @Inject constructor(
vectorBaseActivity.notImplemented("encrypted message click")
}
- override fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View) {
+ override fun onImageMessageClicked(messageImageContent: MessageImageInfoContent,
+ mediaData: ImageContentRenderer.Data,
+ view: View,
+ inMemory: List) {
navigator.openMediaViewer(
activity = requireActivity(),
roomId = timelineArgs.roomId,
mediaData = mediaData,
- view = view
+ view = view,
+ inMemory = inMemory
) { pairs ->
pairs.add(Pair(views.roomToolbar, ViewCompat.getTransitionName(views.roomToolbar) ?: ""))
pairs.add(Pair(views.composerLayout, ViewCompat.getTransitionName(views.composerLayout) ?: ""))
@@ -2047,6 +2063,14 @@ class TimelineFragment @Inject constructor(
messageComposerViewModel.handle(MessageComposerAction.PlayOrPauseVoicePlayback(eventId, messageAudioContent))
}
+ override fun onVoiceWaveformTouchedUp(eventId: String, duration: Int, percentage: Float) {
+ messageComposerViewModel.handle(MessageComposerAction.VoiceWaveformTouchedUp(eventId, duration, percentage))
+ }
+
+ override fun onVoiceWaveformMovedTo(eventId: String, duration: Int, percentage: Float) {
+ messageComposerViewModel.handle(MessageComposerAction.VoiceWaveformMovedTo(eventId, duration, percentage))
+ }
+
private fun onShareActionClicked(action: EventSharedAction.Share) {
when (action.messageContent) {
is MessageTextContent -> shareText(requireContext(), action.messageContent.body)
@@ -2232,6 +2256,8 @@ class TimelineFragment @Inject constructor(
is EventSharedAction.EndPoll -> {
askConfirmationToEndPoll(action.eventId)
}
+ is EventSharedAction.ReportContent -> Unit /* Not clickable */
+ EventSharedAction.Separator -> Unit /* Not clickable */
}
}
@@ -2430,7 +2456,7 @@ class TimelineFragment @Inject constructor(
locationOwnerId = session.myUserId
)
}
- }.exhaustive
+ }
}
// AttachmentsHelper.Callback
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
index a9235b5699..6933adc758 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
@@ -33,7 +33,6 @@ import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -440,7 +439,7 @@ class TimelineViewModel @AssistedInject constructor(
_viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true))
}
is RoomDetailAction.EndPoll -> handleEndPoll(action.eventId)
- }.exhaustive
+ }
}
private fun handleJitsiCallJoinStatus(action: RoomDetailAction.UpdateJoinJitsiCallStatus) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
index 10cef39942..091e9f7869 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
@@ -40,4 +40,6 @@ sealed class MessageComposerAction : VectorViewModelAction {
data class PlayOrPauseVoicePlayback(val eventId: String, val messageAudioContent: MessageAudioContent) : MessageComposerAction()
object PlayOrPauseRecordingPlayback : MessageComposerAction()
data class EndAllVoiceActions(val deleteRecord: Boolean = true) : MessageComposerAction()
+ data class VoiceWaveformTouchedUp(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
+ data class VoiceWaveformMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
index 009d898940..976489eec3 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.analytics.AnalyticsTracker
@@ -109,6 +108,8 @@ class MessageComposerViewModel @AssistedInject constructor(
is MessageComposerAction.EndAllVoiceActions -> handleEndAllVoiceActions(action.deleteRecord)
is MessageComposerAction.InitializeVoiceRecorder -> handleInitializeVoiceRecorder(action.attachmentData)
is MessageComposerAction.OnEntersBackground -> handleEntersBackground(action.composerText)
+ is MessageComposerAction.VoiceWaveformTouchedUp -> handleVoiceWaveformTouchedUp(action)
+ is MessageComposerAction.VoiceWaveformMovedTo -> handleVoiceWaveformMovedTo(action)
}
}
@@ -463,7 +464,7 @@ class MessageComposerViewModel @AssistedInject constructor(
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
popDraft()
}
- }.exhaustive
+ }
}
is SendMode.Edit -> {
// is original event a reply?
@@ -536,7 +537,7 @@ class MessageComposerViewModel @AssistedInject constructor(
is SendMode.Voice -> {
// do nothing
}
- }.exhaustive
+ }
}
}
@@ -869,12 +870,23 @@ class MessageComposerViewModel @AssistedInject constructor(
voiceMessageHelper.pauseRecording()
}
+ private fun handleVoiceWaveformTouchedUp(action: MessageComposerAction.VoiceWaveformTouchedUp) {
+ voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
+ }
+
+ private fun handleVoiceWaveformMovedTo(action: MessageComposerAction.VoiceWaveformMovedTo) {
+ voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
+ }
+
private fun handleEntersBackground(composerText: String) {
+ // Always stop all voice actions. It may be playing in timeline or active recording
+ val playingAudioContent = voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)
+ voiceMessageHelper.clearTracker()
+
val isVoiceRecording = com.airbnb.mvrx.withState(this) { it.isVoiceRecording }
if (isVoiceRecording) {
- voiceMessageHelper.clearTracker()
viewModelScope.launch {
- voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)?.toContentAttachmentData()?.let { voiceDraft ->
+ playingAudioContent?.toContentAttachmentData()?.let { voiceDraft ->
val content = voiceDraft.toJsonString()
room.saveDraft(UserDraft.Voice(content))
setState { copy(sendMode = SendMode.Voice(content)) }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt
index 735d356476..c5d8b7a5c1 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt
@@ -132,9 +132,11 @@ class VoiceMessageHelper @Inject constructor(
}
fun startOrPausePlayback(id: String, file: File) {
- stopPlayback()
+ val playbackState = playbackTracker.getPlaybackState(id)
+ mediaPlayer?.stop()
+ stopPlaybackTicker()
stopRecordingAmplitudes()
- if (playbackTracker.getPlaybackState(id) is VoiceMessagePlaybackTracker.Listener.State.Playing) {
+ if (playbackState is VoiceMessagePlaybackTracker.Listener.State.Playing) {
playbackTracker.pausePlayback(id)
} else {
startPlayback(id, file)
@@ -169,11 +171,19 @@ class VoiceMessageHelper @Inject constructor(
}
fun stopPlayback() {
- playbackTracker.stopPlayback(VoiceMessagePlaybackTracker.RECORDING_ID)
+ playbackTracker.pausePlayback(VoiceMessagePlaybackTracker.RECORDING_ID)
mediaPlayer?.stop()
stopPlaybackTicker()
}
+ fun movePlaybackTo(id: String, percentage: Float, totalDuration: Int) {
+ val toMillisecond = (totalDuration * percentage).toInt()
+ playbackTracker.updateCurrentPlaybackTime(id, toMillisecond, percentage)
+
+ stopPlayback()
+ playbackTracker.pausePlayback(id)
+ }
+
private fun startRecordingAmplitudes() {
amplitudeTicker?.stop()
amplitudeTicker = CountUpTimer(50).apply {
@@ -221,7 +231,9 @@ class VoiceMessageHelper @Inject constructor(
private fun onPlaybackTick(id: String) {
if (mediaPlayer?.isPlaying.orFalse()) {
val currentPosition = mediaPlayer?.currentPosition ?: 0
- playbackTracker.updateCurrentPlaybackTime(id, currentPosition)
+ val totalDuration = mediaPlayer?.duration ?: 0
+ val percentage = currentPosition.toFloat() / totalDuration
+ playbackTracker.updateCurrentPlaybackTime(id, currentPosition, percentage)
} else {
playbackTracker.stopPlayback(id)
stopPlaybackTicker()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
index 9a643796a9..ab37d1a48c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
@@ -23,7 +23,6 @@ import androidx.constraintlayout.widget.ConstraintLayout
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.DimensionConverter
@@ -53,6 +52,8 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
fun onDeleteVoiceMessage()
fun onRecordingLimitReached()
fun onRecordingWaveformClicked()
+ fun onVoiceWaveformTouchedUp(percentage: Float, duration: Int)
+ fun onVoiceWaveformMoved(percentage: Float, duration: Int)
}
@Inject lateinit var clock: Clock
@@ -65,6 +66,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
private var recordingTicker: CountUpTimer? = null
private var lastKnownState: RecordingUiState? = null
private var dragState: DraggingState = DraggingState.Ignored
+ private var recordingDuration: Long = 0
init {
inflate(this.context, R.layout.view_voice_message_recorder, this)
@@ -95,9 +97,9 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
override fun onDeleteVoiceMessage() = callback.onDeleteVoiceMessage()
override fun onWaveformClicked() {
when (lastKnownState) {
- RecordingUiState.Draft -> callback.onVoicePlaybackButtonClicked()
is RecordingUiState.Recording,
is RecordingUiState.Locked -> callback.onRecordingWaveformClicked()
+ else -> Unit
}
}
@@ -105,6 +107,18 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
override fun onMicButtonDrag(nextDragStateCreator: (DraggingState) -> DraggingState) {
onDrag(dragState, newDragState = nextDragStateCreator(dragState))
}
+
+ override fun onVoiceWaveformTouchedUp(percentage: Float) {
+ if (lastKnownState == RecordingUiState.Draft) {
+ callback.onVoiceWaveformTouchedUp(percentage, recordingDuration.toInt())
+ }
+ }
+
+ override fun onVoiceWaveformMoved(percentage: Float) {
+ if (lastKnownState == RecordingUiState.Draft) {
+ callback.onVoiceWaveformMoved(percentage, recordingDuration.toInt())
+ }
+ }
})
}
@@ -119,7 +133,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
fun render(recordingState: RecordingUiState) {
if (lastKnownState == recordingState) return
when (recordingState) {
- RecordingUiState.Idle -> {
+ RecordingUiState.Idle -> {
reset()
}
is RecordingUiState.Recording -> {
@@ -137,7 +151,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
voiceMessageViews.showRecordingLockedViews(recordingState)
}, 500)
}
- RecordingUiState.Draft -> {
+ RecordingUiState.Draft -> {
stopRecordingTicker()
voiceMessageViews.showDraftViews()
}
@@ -167,7 +181,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
DraggingState.Ready -> {
// do nothing
}
- }.exhaustive
+ }
dragState = newDragState
}
@@ -203,6 +217,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
}
private fun stopRecordingTicker() {
+ recordingDuration = recordingTicker?.elapsedTime() ?: 0
recordingTicker?.stop()
recordingTicker = null
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
index 09284ea5fc..7a76657923 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
@@ -27,7 +27,6 @@ import androidx.core.view.doOnLayout
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
-import com.visualizer.amplitude.AudioRecordView
import im.vector.app.R
import im.vector.app.core.extensions.setAttributeBackground
import im.vector.app.core.extensions.setAttributeTintedBackground
@@ -37,6 +36,8 @@ import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.DraggingState
import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.RecordingUiState
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
+import im.vector.app.features.themes.ThemeUtils
+import im.vector.app.features.voice.AudioWaveformView
class VoiceMessageViews(
private val resources: Resources,
@@ -59,8 +60,21 @@ class VoiceMessageViews(
actions.onDeleteVoiceMessage()
}
- views.voicePlaybackWaveform.setOnClickListener {
- actions.onWaveformClicked()
+ views.voicePlaybackWaveform.setOnTouchListener { view, motionEvent ->
+ when (motionEvent.action) {
+ MotionEvent.ACTION_DOWN -> {
+ actions.onWaveformClicked()
+ }
+ MotionEvent.ACTION_UP -> {
+ val percentage = getTouchedPositionPercentage(motionEvent, view)
+ actions.onVoiceWaveformTouchedUp(percentage)
+ }
+ MotionEvent.ACTION_MOVE -> {
+ val percentage = getTouchedPositionPercentage(motionEvent, view)
+ actions.onVoiceWaveformMoved(percentage)
+ }
+ }
+ true
}
views.voicePlaybackControlButton.setOnClickListener {
@@ -69,6 +83,8 @@ class VoiceMessageViews(
observeMicButton(actions)
}
+ private fun getTouchedPositionPercentage(motionEvent: MotionEvent, view: View) = (motionEvent.x / view.width).coerceIn(0f, 1f)
+
@SuppressLint("ClickableViewAccessibility")
private fun observeMicButton(actions: Actions) {
val draggableStateProcessor = DraggableStateProcessor(resources, dimensionConverter)
@@ -284,7 +300,7 @@ class VoiceMessageViews(
hideRecordingViews(RecordingUiState.Idle)
views.voiceMessageMicButton.isVisible = true
views.voiceMessageSendButton.isVisible = false
- views.voicePlaybackWaveform.post { views.voicePlaybackWaveform.recreate() }
+ views.voicePlaybackWaveform.post { views.voicePlaybackWaveform.clear() }
}
fun renderPlaying(state: VoiceMessagePlaybackTracker.Listener.State.Playing) {
@@ -292,11 +308,15 @@ class VoiceMessageViews(
views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_pause_voice_message)
val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong())
views.voicePlaybackTime.text = formattedTimerText
+ val waveformColorIdle = ThemeUtils.getColor(views.voicePlaybackWaveform.context, R.attr.vctr_content_quaternary)
+ val waveformColorPlayed = ThemeUtils.getColor(views.voicePlaybackWaveform.context, R.attr.vctr_content_secondary)
+ views.voicePlaybackWaveform.updateColors(state.percentage, waveformColorPlayed, waveformColorIdle)
}
fun renderIdle() {
views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_play_voice_message)
+ views.voicePlaybackWaveform.summarize()
}
fun renderToast(message: String) {
@@ -327,8 +347,9 @@ class VoiceMessageViews(
fun renderRecordingWaveform(amplitudeList: Array) {
views.voicePlaybackWaveform.doOnLayout { waveFormView ->
+ val waveformColor = ThemeUtils.getColor(waveFormView.context, R.attr.vctr_content_quaternary)
amplitudeList.iterator().forEach {
- (waveFormView as AudioRecordView).update(it)
+ (waveFormView as AudioWaveformView).add(AudioWaveformView.FFT(it.toFloat(), waveformColor))
}
}
}
@@ -349,5 +370,7 @@ class VoiceMessageViews(
fun onDeleteVoiceMessage()
fun onWaveformClicked()
fun onVoicePlaybackButtonClicked()
+ fun onVoiceWaveformTouchedUp(percentage: Float)
+ fun onVoiceWaveformMoved(percentage: Float)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
index 62c142238e..fbcf29d863 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
@@ -26,6 +26,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
@@ -88,6 +89,7 @@ class SearchFragment @Inject constructor(
override fun invalidate() = withState(searchViewModel) { state ->
if (state.searchResult.isNullOrEmpty()) {
when (state.asyncSearchRequest) {
+ Uninitialized,
is Loading -> {
views.stateView.state = StateView.State.Loading
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt
index 7bff76cc36..1702fb95cd 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
@@ -56,7 +55,7 @@ class SearchViewModel @AssistedInject constructor(
is SearchAction.SearchWith -> handleSearchWith(action)
is SearchAction.LoadMore -> handleLoadMore()
is SearchAction.Retry -> handleRetry()
- }.exhaustive
+ }
}
private fun handleSearchWith(action: SearchAction.SearchWith) {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
index fb47fb5136..023c28cdc7 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
@@ -57,6 +57,7 @@ import im.vector.app.features.home.room.detail.timeline.item.ReactionsSummaryEve
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptsItem
import im.vector.app.features.home.room.detail.timeline.url.PreviewUrlRetriever
+import im.vector.app.features.media.AttachmentData
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.settings.VectorPreferences
@@ -127,7 +128,10 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
fun onEventVisible(event: TimelineEvent)
fun onRoomCreateLinkClicked(url: String)
fun onEncryptedMessageClicked(informationData: MessageInformationData, view: View)
- fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View)
+ fun onImageMessageClicked(messageImageContent: MessageImageInfoContent,
+ mediaData: ImageContentRenderer.Data,
+ view: View,
+ inMemory: List)
fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: VideoContentRenderer.Data, view: View)
// fun onFileMessageClicked(eventId: String, messageFileContent: MessageFileContent)
@@ -141,6 +145,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
fun getPreviewUrlRetriever(): PreviewUrlRetriever
fun onVoiceControlButtonClicked(eventId: String, messageAudioContent: MessageAudioContent)
+ fun onVoiceWaveformTouchedUp(eventId: String, duration: Int, percentage: Float)
+ fun onVoiceWaveformMovedTo(eventId: String, duration: Int, percentage: Float)
fun onAddMoreReaction(event: TimelineEvent)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
index 1dad6cc4a7..9f05547300 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
@@ -18,8 +18,9 @@ package im.vector.app.features.home.room.detail.timeline.edithistory
import android.text.Spannable
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
import im.vector.app.core.date.DateFormatKind
import im.vector.app.core.date.VectorDateFormatter
@@ -54,18 +55,19 @@ class ViewEditHistoryEpoxyController @Inject constructor(
override fun buildModels(state: ViewEditHistoryViewState) {
val host = this
when (state.editList) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
genericLoaderItem {
id("Spinner")
}
}
- is Fail -> {
+ is Fail -> {
genericFooterItem {
id("failure")
text(host.stringProvider.getString(R.string.unknown_error).toEpoxyCharSequence())
}
}
- is Success -> {
+ is Success -> {
state.editList()?.let { renderEvents(it, state.isOriginalAReply) }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index 3189954e20..9c15532376 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -74,6 +74,7 @@ import im.vector.app.features.location.toLocationData
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.settings.VectorPreferences
+import im.vector.app.features.voice.AudioWaveformView
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import me.gujun.android.span.span
import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl
@@ -362,11 +363,24 @@ class MessageItemFactory @Inject constructor(
}
}
+ val waveformTouchListener: MessageVoiceItem.WaveformTouchListener = object : MessageVoiceItem.WaveformTouchListener {
+ override fun onWaveformTouchedUp(percentage: Float) {
+ val duration = messageContent.audioInfo?.duration ?: 0
+ params.callback?.onVoiceWaveformTouchedUp(informationData.eventId, duration, percentage)
+ }
+
+ override fun onWaveformMovedTo(percentage: Float) {
+ val duration = messageContent.audioInfo?.duration ?: 0
+ params.callback?.onVoiceWaveformMovedTo(informationData.eventId, duration, percentage)
+ }
+ }
+
return MessageVoiceItem_()
.attributes(attributes)
.duration(messageContent.audioWaveformInfo?.duration ?: 0)
.waveform(messageContent.audioWaveformInfo?.waveform?.toFft().orEmpty())
.playbackControlButtonClickListener(playbackControlButtonClickListener)
+ .waveformTouchListener(waveformTouchListener)
.voiceMessagePlaybackTracker(voiceMessagePlaybackTracker)
.izLocalFile(localFilesHelper.isLocalFile(fileUrl))
.izDownloaded(session.fileService().isFileInCache(
@@ -480,9 +494,12 @@ class MessageItemFactory @Inject constructor(
.apply {
if (messageContent.msgType == MessageType.MSGTYPE_STICKER_LOCAL) {
mode(ImageContentRenderer.Mode.STICKER)
+ clickListener { view ->
+ callback?.onImageMessageClicked(messageContent, data, view, listOf(data))
+ }
} else {
clickListener { view ->
- callback?.onImageMessageClicked(messageContent, data, view)
+ callback?.onImageMessageClicked(messageContent, data, view, emptyList())
}
}
}
@@ -696,8 +713,8 @@ class MessageItemFactory @Inject constructor(
return this
?.filterNotNull()
?.map {
- // Value comes from AudioRecordView.maxReportableAmp, and 1024 is the max value in the Matrix spec
- it * 22760 / 1024
+ // Value comes from AudioWaveformView.MAX_FFT, and 1024 is the max value in the Matrix spec
+ it * AudioWaveformView.MAX_FFT / 1024
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
index 0909cbe8de..9ff8ddfbce 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt
@@ -26,7 +26,6 @@ import dagger.hilt.android.scopes.ActivityScoped
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.utils.TextUtils
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
@@ -86,7 +85,7 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup,
is ContentUploadStateTracker.State.Success -> handleSuccess()
is ContentUploadStateTracker.State.CompressingImage -> handleCompressingImage()
is ContentUploadStateTracker.State.CompressingVideo -> handleCompressingVideo(state)
- }.exhaustive
+ }
}
private fun handleIdle() {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt
index c6204bff1c..8167ad94af 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt
@@ -70,7 +70,8 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
fun startPlayback(id: String) {
val currentPlaybackTime = getPlaybackTime(id)
- val currentState = Listener.State.Playing(currentPlaybackTime)
+ val currentPercentage = getPercentage(id)
+ val currentState = Listener.State.Playing(currentPlaybackTime, currentPercentage)
setState(id, currentState)
// Pause any active playback
states
@@ -87,15 +88,16 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
fun pausePlayback(id: String) {
val currentPlaybackTime = getPlaybackTime(id)
- setState(id, Listener.State.Paused(currentPlaybackTime))
+ val currentPercentage = getPercentage(id)
+ setState(id, Listener.State.Paused(currentPlaybackTime, currentPercentage))
}
fun stopPlayback(id: String) {
setState(id, Listener.State.Idle)
}
- fun updateCurrentPlaybackTime(id: String, time: Int) {
- setState(id, Listener.State.Playing(time))
+ fun updateCurrentPlaybackTime(id: String, time: Int, percentage: Float) {
+ setState(id, Listener.State.Playing(time, percentage))
}
fun updateCurrentRecording(id: String, amplitudeList: List) {
@@ -113,6 +115,15 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
}
}
+ private fun getPercentage(id: String): Float {
+ return when (val state = states[id]) {
+ is Listener.State.Playing -> state.percentage
+ is Listener.State.Paused -> state.percentage
+ /* Listener.State.Idle, */
+ else -> 0f
+ }
+ }
+
fun clear() {
listeners.forEach {
it.value.onUpdate(Listener.State.Idle)
@@ -131,8 +142,8 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
sealed class State {
object Idle : State()
- data class Playing(val playbackTime: Int) : State()
- data class Paused(val playbackTime: Int) : State()
+ data class Playing(val playbackTime: Int, val percentage: Float) : State()
+ data class Paused(val playbackTime: Int, val percentage: Float) : State()
data class Recording(val amplitudeList: List) : State()
}
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
index e9f728d976..aad30ef41e 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
@@ -19,14 +19,15 @@ package im.vector.app.features.home.room.detail.timeline.item
import android.content.res.ColorStateList
import android.graphics.Color
import android.text.format.DateUtils
+import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
+import androidx.core.view.doOnLayout
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
-import com.visualizer.amplitude.AudioRecordView
import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
@@ -34,10 +35,16 @@ import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStat
import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.themes.ThemeUtils
+import im.vector.app.features.voice.AudioWaveformView
@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
abstract class MessageVoiceItem : AbsMessageItem() {
+ interface WaveformTouchListener {
+ fun onWaveformTouchedUp(percentage: Float)
+ fun onWaveformMovedTo(percentage: Float)
+ }
+
@EpoxyAttribute
var mxcUrl: String = ""
@@ -62,6 +69,9 @@ abstract class MessageVoiceItem : AbsMessageItem() {
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var playbackControlButtonClickListener: ClickListener? = null
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var waveformTouchListener: WaveformTouchListener? = null
+
@EpoxyAttribute
lateinit var voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker
@@ -76,13 +86,8 @@ abstract class MessageVoiceItem : AbsMessageItem() {
holder.progressLayout.isVisible = false
}
- holder.voicePlaybackWaveform.setOnLongClickListener(attributes.itemLongClickListener)
-
- holder.voicePlaybackWaveform.post {
- holder.voicePlaybackWaveform.recreate()
- waveform.forEach { amplitude ->
- holder.voicePlaybackWaveform.update(amplitude)
- }
+ holder.voicePlaybackWaveform.doOnLayout {
+ onWaveformViewReady(holder)
}
val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) {
@@ -92,34 +97,67 @@ abstract class MessageVoiceItem : AbsMessageItem() {
}
holder.voicePlaybackLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint)
holder.voicePlaybackControlButton.setOnClickListener { playbackControlButtonClickListener?.invoke(it) }
+ }
+
+ private fun onWaveformViewReady(holder: Holder) {
+ holder.voicePlaybackWaveform.setOnLongClickListener(attributes.itemLongClickListener)
+
+ val waveformColorIdle = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quaternary)
+ val waveformColorPlayed = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
+
+ holder.voicePlaybackWaveform.clear()
+ waveform.forEach { amplitude ->
+ holder.voicePlaybackWaveform.add(AudioWaveformView.FFT(amplitude.toFloat(), waveformColorIdle))
+ }
+ holder.voicePlaybackWaveform.summarize()
+
+ holder.voicePlaybackWaveform.setOnTouchListener { view, motionEvent ->
+ when (motionEvent.action) {
+ MotionEvent.ACTION_UP -> {
+ val percentage = getTouchedPositionPercentage(motionEvent, view)
+ waveformTouchListener?.onWaveformTouchedUp(percentage)
+ }
+ MotionEvent.ACTION_MOVE -> {
+ val percentage = getTouchedPositionPercentage(motionEvent, view)
+ waveformTouchListener?.onWaveformMovedTo(percentage)
+ }
+ }
+ true
+ }
voiceMessagePlaybackTracker.track(attributes.informationData.eventId, object : VoiceMessagePlaybackTracker.Listener {
override fun onUpdate(state: VoiceMessagePlaybackTracker.Listener.State) {
when (state) {
- is VoiceMessagePlaybackTracker.Listener.State.Idle -> renderIdleState(holder)
- is VoiceMessagePlaybackTracker.Listener.State.Playing -> renderPlayingState(holder, state)
- is VoiceMessagePlaybackTracker.Listener.State.Paused -> renderPausedState(holder, state)
+ is VoiceMessagePlaybackTracker.Listener.State.Idle -> renderIdleState(holder, waveformColorIdle, waveformColorPlayed)
+ is VoiceMessagePlaybackTracker.Listener.State.Playing -> renderPlayingState(holder, state, waveformColorIdle, waveformColorPlayed)
+ is VoiceMessagePlaybackTracker.Listener.State.Paused -> renderPausedState(holder, state, waveformColorIdle, waveformColorPlayed)
+ is VoiceMessagePlaybackTracker.Listener.State.Recording -> Unit
}
}
})
}
- private fun renderIdleState(holder: Holder) {
+ private fun getTouchedPositionPercentage(motionEvent: MotionEvent, view: View) = (motionEvent.x / view.width).coerceIn(0f, 1f)
+
+ private fun renderIdleState(holder: Holder, idleColor: Int, playedColor: Int) {
holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message)
holder.voicePlaybackTime.text = formatPlaybackTime(duration)
+ holder.voicePlaybackWaveform.updateColors(0f, playedColor, idleColor)
}
- private fun renderPlayingState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Playing) {
+ private fun renderPlayingState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Playing, idleColor: Int, playedColor: Int) {
holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_pause_voice_message)
holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
+ holder.voicePlaybackWaveform.updateColors(state.percentage, playedColor, idleColor)
}
- private fun renderPausedState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Paused) {
+ private fun renderPausedState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Paused, idleColor: Int, playedColor: Int) {
holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message)
holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
+ holder.voicePlaybackWaveform.updateColors(state.percentage, playedColor, idleColor)
}
private fun formatPlaybackTime(time: Int) = DateUtils.formatElapsedTime((time / 1000).toLong())
@@ -138,7 +176,7 @@ abstract class MessageVoiceItem : AbsMessageItem() {
val voiceLayout by bind(R.id.voiceLayout)
val voicePlaybackControlButton by bind(R.id.voicePlaybackControlButton)
val voicePlaybackTime by bind(R.id.voicePlaybackTime)
- val voicePlaybackWaveform by bind(R.id.voicePlaybackWaveform)
+ val voicePlaybackWaveform by bind(R.id.voicePlaybackWaveform)
val progressLayout by bind(R.id.messageFileUploadProgressLayout)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt
index 2be933d9c3..80daa595b6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollOptionView.kt
@@ -23,7 +23,6 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setAttributeTintedImageResource
import im.vector.app.databinding.ItemPollOptionBinding
@@ -49,7 +48,7 @@ class PollOptionView @JvmOverloads constructor(
is PollOptionViewState.PollReady -> renderPollReady()
is PollOptionViewState.PollVoted -> renderPollVoted(state)
is PollOptionViewState.PollUndisclosed -> renderPollUndisclosed(state)
- }.exhaustive
+ }
}
private fun renderPollSending() {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
index 821531416b..61fcddd123 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
@@ -31,7 +31,6 @@ import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.onClick
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
@@ -105,7 +104,7 @@ abstract class VerificationRequestItem : AbsBaseMessageItem {
+ Uninitialized,
+ is Loading -> {
genericLoaderItem {
id("Spinner")
}
}
- is Fail -> {
+ is Fail -> {
genericFooterItem {
id("failure")
text(host.stringProvider.getString(R.string.unknown_error).toEpoxyCharSequence())
}
}
- is Success -> {
+ is Success -> {
state.mapReactionKeyToMemberList()?.forEach { reactionInfo ->
reactionInfoSimpleItem {
id(reactionInfo.eventId)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
index 4265eebe62..a827966a58 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
@@ -38,7 +38,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.epoxy.LayoutManagerStateRestorer
import im.vector.app.core.extensions.cleanup
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.StateView
import im.vector.app.core.platform.VectorBaseFragment
@@ -128,7 +127,7 @@ class RoomListFragment @Inject constructor(
is RoomListViewEvents.SelectRoom -> handleSelectRoom(it, it.isInviteAlreadyAccepted)
is RoomListViewEvents.Done -> Unit
is RoomListViewEvents.NavigateToMxToBottomSheet -> handleShowMxToLink(it.link)
- }.exhaustive
+ }
}
views.createChatFabMenu.listener = this
@@ -295,7 +294,8 @@ class RoomListFragment @Inject constructor(
section.notificationCount.observe(viewLifecycleOwner) { counts ->
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
notificationCount = counts.totalCount,
- isHighlighted = counts.isHighlight
+ isHighlighted = counts.isHighlight,
+ shouldShowExpandedArrow = shouldShowExpendedArrow()
))
}
section.isExpanded.observe(viewLifecycleOwner) { _ ->
@@ -329,14 +329,17 @@ class RoomListFragment @Inject constructor(
controller.setData(list)
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
isHidden = list.isEmpty(),
- isLoading = false))
+ isLoading = false,
+ shouldShowExpandedArrow = shouldShowExpendedArrow()
+ ))
checkEmptyState()
}
observeItemCount(section, sectionAdapter)
section.notificationCount.observe(viewLifecycleOwner) { counts ->
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy(
notificationCount = counts.totalCount,
- isHighlighted = counts.isHighlight
+ isHighlighted = counts.isHighlight,
+ shouldShowExpandedArrow = shouldShowExpendedArrow()
))
}
section.isExpanded.observe(viewLifecycleOwner) { _ ->
@@ -418,7 +421,7 @@ class RoomListFragment @Inject constructor(
is RoomListQuickActionsSharedAction.Leave -> {
promptLeaveRoom(quickAction.roomId)
}
- }.exhaustive
+ }
}
private fun promptLeaveRoom(roomId: String) {
@@ -444,6 +447,10 @@ class RoomListFragment @Inject constructor(
footerController.setData(state)
}
+ private fun shouldShowExpendedArrow(): Boolean {
+ return adapterInfosList.filter { !it.sectionHeaderAdapter.roomsSectionData.isHidden }.size >= 2
+ }
+
private fun checkEmptyState() {
val shouldShowEmpty = adapterInfosList.all { it.sectionHeaderAdapter.roomsSectionData.isHidden } &&
!adapterInfosList.any { it.sectionHeaderAdapter.roomsSectionData.isLoading }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
index ec8b01876b..70974bc1f6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt
@@ -29,7 +29,6 @@ import im.vector.app.AppStateHandler
import im.vector.app.RoomGroupingMethod
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.analytics.AnalyticsTracker
@@ -163,7 +162,7 @@ class RoomListViewModel @AssistedInject constructor(
is RoomListAction.ToggleSection -> handleToggleSection(action.section)
is RoomListAction.JoinSuggestedRoom -> handleJoinSuggestedRoom(action)
is RoomListAction.ShowRoomDetails -> handleShowRoomDetails(action)
- }.exhaustive
+ }
}
fun isPublicRoom(roomId: String): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt b/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt
index 2e6436d21d..cd2879cf28 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/SectionHeaderAdapter.kt
@@ -17,6 +17,7 @@
package im.vector.app.features.home.room.list
import android.view.LayoutInflater
+import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
@@ -39,7 +40,8 @@ class SectionHeaderAdapter constructor(
val isHighlighted: Boolean = false,
val isHidden: Boolean = true,
// This will be false until real data has been submitted once
- val isLoading: Boolean = true
+ val isLoading: Boolean = true,
+ val shouldShowExpandedArrow: Boolean = false
)
lateinit var roomsSectionData: RoomsSectionData
@@ -82,11 +84,16 @@ class SectionHeaderAdapter constructor(
fun bind(roomsSectionData: RoomsSectionData) {
binding.roomCategoryTitleView.text = roomsSectionData.name
val tintColor = ThemeUtils.getColor(binding.root.context, R.attr.vctr_content_secondary)
- val expandedArrowDrawableRes = if (roomsSectionData.isExpanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
- val expandedArrowDrawable = ContextCompat.getDrawable(binding.root.context, expandedArrowDrawableRes)?.also {
- DrawableCompat.setTint(it, tintColor)
+ if (roomsSectionData.shouldShowExpandedArrow) {
+ binding.roomCategoryCounterView.visibility = View.VISIBLE
+ val expandedArrowDrawableRes = if (roomsSectionData.isExpanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
+ val expandedArrowDrawable = ContextCompat.getDrawable(binding.root.context, expandedArrowDrawableRes)?.also {
+ DrawableCompat.setTint(it, tintColor)
+ }
+ binding.roomCategoryCounterView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
+ } else {
+ binding.roomCategoryCounterView.visibility = View.GONE
}
- binding.roomCategoryCounterView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
binding.roomCategoryCounterView.text = roomsSectionData.itemCount.takeIf { it > 0 }?.toString().orEmpty()
binding.roomCategoryUnreadCounterBadgeView.render(UnreadCounterBadgeView.State(roomsSectionData.notificationCount, roomsSectionData.isHighlighted))
}
diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt
index 48a70fb164..7bb6670e96 100644
--- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt
@@ -74,8 +74,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() {
is UserListSharedAction.OnMenuItemSelected -> onMenuItemSelected(sharedAction)
UserListSharedAction.OpenPhoneBook -> openPhoneBook()
// not exhaustive because it's a sharedAction
- else -> {
- }
+ else -> Unit
}
}
.launchIn(lifecycleScope)
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
index 84efff0e0d..d4582d98b9 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt
@@ -31,7 +31,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.mapbox.mapboxsdk.maps.MapView
import im.vector.app.BuildConfig
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.PERMISSIONS_FOR_BACKGROUND_LOCATION_SHARING
import im.vector.app.core.utils.PERMISSIONS_FOR_FOREGROUND_LOCATION_SHARING
@@ -89,7 +88,7 @@ class LocationSharingFragment @Inject constructor(
LocationSharingViewEvents.LocationNotAvailableError -> handleLocationNotAvailableError()
is LocationSharingViewEvents.ZoomToUserLocation -> handleZoomToUserLocationEvent(it)
is LocationSharingViewEvents.StartLiveLocationService -> handleStartLiveLocationService(it)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
index 8293ac6143..347aad7db9 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.location.domain.usecase.CompareLocationsUseCase
@@ -123,7 +122,7 @@ class LocationSharingViewModel @AssistedInject constructor(
is LocationSharingAction.LocationTargetChange -> handleLocationTargetChangeAction(action)
LocationSharingAction.ZoomToUserLocation -> handleZoomToUserLocationAction()
is LocationSharingAction.StartLiveLocationSharing -> handleStartLiveLocationSharingAction(action.duration)
- }.exhaustive
+ }
}
private fun handleCurrentUserLocationSharingAction() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/location/live/LocationLiveStatusView.kt b/vector/src/main/java/im/vector/app/features/location/live/LocationLiveStatusView.kt
new file mode 100644
index 0000000000..a4c58c9e5b
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/location/live/LocationLiveStatusView.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.location.live
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.Button
+import androidx.constraintlayout.widget.ConstraintLayout
+import im.vector.app.databinding.ViewLocationLiveStatusBinding
+
+class LocationLiveStatusView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+ private val binding = ViewLocationLiveStatusBinding.inflate(
+ LayoutInflater.from(context),
+ this
+ )
+
+ val stopButton: Button
+ get() = binding.locationLiveStatusStop
+}
diff --git a/vector/src/main/java/im/vector/app/features/login/AbstractLoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/AbstractLoginFragment.kt
index 8b83873142..f5e48e84e7 100644
--- a/vector/src/main/java/im/vector/app/features/login/AbstractLoginFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/AbstractLoginFragment.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import kotlinx.coroutines.CancellationException
@@ -69,7 +68,7 @@ abstract class AbstractLoginFragment : VectorBaseFragment(
else ->
// This is handled by the Activity
Unit
- }.exhaustive
+ }
}
override fun showFailure(throwable: Throwable) {
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
index a40f26acec..dec6fef040 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
@@ -35,7 +35,6 @@ import im.vector.app.R
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.validateBackPressed
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityLoginBinding
@@ -197,7 +196,7 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA
is LoginViewEvents.Loading ->
// This is handled by the Fragments
Unit
- }.exhaustive
+ }
}
private fun updateWithState(loginViewState: LoginViewState) {
@@ -260,13 +259,13 @@ open class LoginActivity : VectorBaseActivity(), UnlockedA
tag = FRAGMENT_LOGIN_TAG,
option = commonOption)
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
- }.exhaustive
+ }
}
SignMode.SignInWithMatrixId -> addFragmentToBackstack(views.loginFragmentContainer,
LoginFragment::class.java,
tag = FRAGMENT_LOGIN_TAG,
option = commonOption)
- }.exhaustive
+ }
}
/**
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt
index da61d95997..22f8792078 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginFragment.kt
@@ -29,8 +29,8 @@ import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.hidePassword
import im.vector.app.core.extensions.toReducedUrl
@@ -97,7 +97,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment SocialLoginButtonsView.Mode.MODE_SIGN_UP
SignMode.SignIn,
SignMode.SignInWithMatrixId -> SocialLoginButtonsView.Mode.MODE_SIGN_IN
- }.exhaustive
+ }
}
private fun submit() {
@@ -269,6 +269,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment {
// Ensure password is hidden
views.passwordField.hidePassword()
@@ -300,7 +301,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment Unit
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt
index d121245532..1d32944f9f 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordFragment.kt
@@ -23,7 +23,6 @@ import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
-import com.airbnb.mvrx.Success
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
@@ -129,7 +128,7 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment {
views.resetPasswordEmailTil.error = errorFormatter.toHumanReadable(state.asyncResetPassword.error)
}
- is Success -> Unit
+ else -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt
index 5f376700f8..232e7ab622 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginResetPasswordMailConfirmationFragment.kt
@@ -21,7 +21,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Success
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.databinding.FragmentLoginResetPasswordMailConfirmationBinding
@@ -59,7 +58,7 @@ class LoginResetPasswordMailConfirmationFragment @Inject constructor() : Abstrac
setupUi(state)
when (state.asyncResetMailConfirmed) {
- is Fail -> {
+ is Fail -> {
// Link in email not yet clicked ?
val message = if (state.asyncResetMailConfirmed.error.is401()) {
getString(R.string.auth_reset_password_error_unauthorized)
@@ -73,7 +72,7 @@ class LoginResetPasswordMailConfirmationFragment @Inject constructor() : Abstrac
.setPositiveButton(R.string.ok, null)
.show()
}
- is Success -> Unit
+ else -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
index bfa924c155..246c3ad464 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
@@ -31,7 +31,6 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.configureAndStart
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ensureTrailingSlash
@@ -131,7 +130,7 @@ class LoginViewModel @AssistedInject constructor(
is LoginAction.UserAcceptCertificate -> handleUserAcceptCertificate(action)
LoginAction.ClearHomeServerHistory -> handleClearHomeServerHistory()
is LoginAction.PostViewEvent -> _viewEvents.post(action.viewEvent)
- }.exhaustive
+ }
}
private fun handleOnGetStarted(action: LoginAction.OnGetStarted) {
@@ -173,6 +172,7 @@ class LoginViewModel @AssistedInject constructor(
.withAllowedFingerPrints(listOf(action.fingerprint))
.build()
)
+ else -> Unit
}
}
@@ -447,7 +447,7 @@ class LoginViewModel @AssistedInject constructor(
handle(LoginAction.UpdateHomeServer(matrixOrgUrl))
ServerType.EMS,
ServerType.Other -> _viewEvents.post(LoginViewEvents.OnServerSelectionDone(action.serverType))
- }.exhaustive
+ }
}
private fun handleInitWith(action: LoginAction.InitWith) {
@@ -555,7 +555,7 @@ class LoginViewModel @AssistedInject constructor(
SignMode.SignIn -> handleLogin(action)
SignMode.SignUp -> handleRegisterWith(action)
SignMode.SignInWithMatrixId -> handleDirectLogin(action, null)
- }.exhaustive
+ }
}
private fun handleDirectLogin(action: LoginAction.LoginOrRegister, homeServerConnectionConfig: HomeServerConnectionConfig?) {
@@ -585,7 +585,7 @@ class LoginViewModel @AssistedInject constructor(
else -> {
onWellKnownError()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login2/AbstractLoginFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/AbstractLoginFragment2.kt
index 8c9749d91e..68568d1420 100644
--- a/vector/src/main/java/im/vector/app/features/login2/AbstractLoginFragment2.kt
+++ b/vector/src/main/java/im/vector/app/features/login2/AbstractLoginFragment2.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import kotlinx.coroutines.CancellationException
@@ -67,7 +66,7 @@ abstract class AbstractLoginFragment2 : VectorBaseFragment
else ->
// This is handled by the Activity
Unit
- }.exhaustive
+ }
}
override fun showFailure(throwable: Throwable) {
diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt
index b73988126b..8125c6e089 100644
--- a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt
+++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt
@@ -18,7 +18,6 @@ package im.vector.app.features.login2
import android.content.Context
import android.net.Uri
-import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModelFactory
import dagger.assisted.Assisted
@@ -29,7 +28,6 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.configureAndStart
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.tryAsync
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -137,7 +135,7 @@ class LoginViewModel2 @AssistedInject constructor(
LoginAction2.ClearHomeServerHistory -> handleClearHomeServerHistory()
is LoginAction2.PostViewEvent -> _viewEvents.post(action.viewEvent)
is LoginAction2.Finish -> handleFinish()
- }.exhaustive
+ }
}
private fun handleFinish() {
@@ -172,6 +170,7 @@ class LoginViewModel2 @AssistedInject constructor(
handleSetUserPassword(finalLastAction)
is LoginAction2.LoginWith ->
handleLoginWith(finalLastAction)
+ else -> Unit
}
}
@@ -500,7 +499,7 @@ class LoginViewModel2 @AssistedInject constructor(
SignMode2.Unknown -> error("Developer error, invalid sign mode")
SignMode2.SignIn -> handleSetUserNameForSignIn(action, null)
SignMode2.SignUp -> handleSetUserNameForSignUp(action)
- }.exhaustive
+ }
}
private fun handleSetUserPassword(action: LoginAction2.SetUserPassword) = withState { state ->
@@ -508,7 +507,7 @@ class LoginViewModel2 @AssistedInject constructor(
SignMode2.Unknown -> error("Developer error, invalid sign mode")
SignMode2.SignIn -> handleSignInWithPassword(action)
SignMode2.SignUp -> handleRegisterWithPassword(action)
- }.exhaustive
+ }
}
private fun handleRegisterWithPassword(action: LoginAction2.SetUserPassword) = withState { state ->
@@ -588,7 +587,7 @@ class LoginViewModel2 @AssistedInject constructor(
else -> {
onWellKnownError()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt
index 63e0398fc1..61dcd48779 100644
--- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheet.kt
@@ -65,18 +65,17 @@ class MatrixToBottomSheet :
override fun invalidate() = withState(viewModel) { state ->
super.invalidate()
when (state.linkType) {
- is PermalinkData.RoomLink -> {
+ is PermalinkData.RoomLink -> {
views.matrixToCardContentLoading.isVisible = state.roomPeekResult is Incomplete
showFragment(MatrixToRoomSpaceFragment::class, Bundle())
}
- is PermalinkData.UserLink -> {
+ is PermalinkData.UserLink -> {
views.matrixToCardContentLoading.isVisible = state.matrixItem is Incomplete
showFragment(MatrixToUserFragment::class, Bundle())
}
- is PermalinkData.GroupLink -> {
- }
- is PermalinkData.FallbackLink -> {
- }
+ is PermalinkData.GroupLink -> Unit
+ is PermalinkData.FallbackLink -> Unit
+ is PermalinkData.RoomEmailInviteLink -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt
index e741f6fb39..04c2c8dd44 100644
--- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt
@@ -28,7 +28,6 @@ import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.createdirect.DirectRoomHelper
@@ -49,8 +48,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
private val session: Session,
private val stringProvider: StringProvider,
private val directRoomHelper: DirectRoomHelper,
- private val errorFormatter: ErrorFormatter) :
- VectorViewModel(initialState) {
+ private val errorFormatter: ErrorFormatter
+) : VectorViewModel(initialState) {
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory {
@@ -61,22 +60,23 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
init {
when (initialState.linkType) {
- is PermalinkData.RoomLink -> {
+ is PermalinkData.RoomLink -> {
setState {
copy(roomPeekResult = Loading())
}
}
- is PermalinkData.UserLink -> {
+ is PermalinkData.UserLink -> {
setState {
copy(matrixItem = Loading())
}
}
- is PermalinkData.GroupLink -> {
+ is PermalinkData.GroupLink -> {
// Not yet supported
}
- is PermalinkData.FallbackLink -> {
+ is PermalinkData.FallbackLink -> {
// Not yet supported
}
+ is PermalinkData.RoomEmailInviteLink -> Unit
}
viewModelScope.launch(Dispatchers.IO) {
resolveLink(initialState)
@@ -263,7 +263,7 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
is MatrixToAction.OpenRoom -> {
_viewEvents.post(MatrixToViewEvents.NavigateToRoom(action.roomId))
}
- }.exhaustive
+ }
}
private fun handleJoinSpace(joinSpace: MatrixToAction.JoinSpace) {
diff --git a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
index 1e0a3a2ad9..781a176550 100644
--- a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
+++ b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt
@@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
@@ -52,7 +53,10 @@ class RoomEventsAttachmentProvider(
override fun getAttachmentInfoAt(position: Int): AttachmentInfo {
return getItem(position).let {
- val content = it.root.getClearContent().toModel() as? MessageWithAttachmentContent
+ val clearContent = it.root.getClearContent()
+ val content = clearContent.toModel()
+ ?: clearContent.toModel()
+ as? MessageWithAttachmentContent
if (content is MessageImageContent) {
val data = ImageContentRenderer.Data(
eventId = it.eventId,
@@ -66,6 +70,33 @@ class RoomEventsAttachmentProvider(
height = null,
allowNonMxcUrls = it.root.sendState.isSending()
+ )
+ if (content.mimeType == MimeTypes.Gif) {
+ AttachmentInfo.AnimatedImage(
+ uid = it.eventId,
+ url = content.url ?: "",
+ data = data
+ )
+ } else {
+ AttachmentInfo.Image(
+ uid = it.eventId,
+ url = content.url ?: "",
+ data = data
+ )
+ }
+ } else if (content is MessageStickerContent) {
+ val data = ImageContentRenderer.Data(
+ eventId = it.eventId,
+ filename = content.body,
+ mimeType = content.mimeType,
+ url = content.getFileUrl(),
+ elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(),
+ maxHeight = -1,
+ maxWidth = -1,
+ width = null,
+ height = null,
+ allowNonMxcUrls = false
+
)
if (content.mimeType == MimeTypes.Gif) {
AttachmentInfo.AnimatedImage(
diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
index cc02687d93..4c3ce80339 100644
--- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
+++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt
@@ -320,6 +320,7 @@ class DefaultNavigator @Inject constructor(
}
}
}
+ null -> Unit
}
}
@@ -376,6 +377,7 @@ class DefaultNavigator @Inject constructor(
context.startActivity(intent)
}
}
+ null -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt
index 4078bb0b5c..e0e21a39a7 100644
--- a/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt
+++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt
@@ -47,11 +47,9 @@ class NotificationRenderer @Inject constructor(private val notificationDisplayer
)
// Remove summary first to avoid briefly displaying it after dismissing the last notification
- when (summaryNotification) {
- SummaryNotification.Removed -> {
- Timber.d("Removing summary notification")
- notificationDisplayer.cancelNotificationMessage(null, SUMMARY_NOTIFICATION_ID)
- }
+ if (summaryNotification == SummaryNotification.Removed) {
+ Timber.d("Removing summary notification")
+ notificationDisplayer.cancelNotificationMessage(null, SUMMARY_NOTIFICATION_ID)
}
roomNotifications.forEach { wrapper ->
@@ -94,11 +92,9 @@ class NotificationRenderer @Inject constructor(private val notificationDisplayer
}
// Update summary last to avoid briefly displaying it before other notifications
- when (summaryNotification) {
- is SummaryNotification.Update -> {
- Timber.d("Updating summary notification")
- notificationDisplayer.showNotificationMessage(null, SUMMARY_NOTIFICATION_ID, summaryNotification.notification)
- }
+ if (summaryNotification is SummaryNotification.Update) {
+ Timber.d("Updating summary notification")
+ notificationDisplayer.showNotificationMessage(null, SUMMARY_NOTIFICATION_ID, summaryNotification.notification)
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/Login2Variant.kt b/vector/src/main/java/im/vector/app/features/onboarding/Login2Variant.kt
index 107c08da5a..163af5d8d1 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/Login2Variant.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/Login2Variant.kt
@@ -30,7 +30,6 @@ import im.vector.app.R
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.resetBackstack
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityLoginBinding
@@ -257,7 +256,7 @@ class Login2Variant(
is LoginViewEvents2.OnSessionCreated -> handleOnSessionCreated(event)
is LoginViewEvents2.Finish -> terminate(true)
is LoginViewEvents2.CancelRegistration -> handleCancelRegistration()
- }.exhaustive
+ }
}
private fun handleCancelRegistration() {
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt
index 4f16231747..7fa75d1544 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt
@@ -22,63 +22,49 @@ import im.vector.app.features.login.LoginConfig
import im.vector.app.features.login.ServerType
import im.vector.app.features.login.SignMode
import org.matrix.android.sdk.api.auth.data.Credentials
-import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import org.matrix.android.sdk.internal.network.ssl.Fingerprint
-sealed class OnboardingAction : VectorViewModelAction {
- data class OnGetStarted(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction()
- data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction()
+sealed interface OnboardingAction : VectorViewModelAction {
+ data class OnGetStarted(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction
+ data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction
- data class UpdateServerType(val serverType: ServerType) : OnboardingAction()
- data class UpdateHomeServer(val homeServerUrl: String) : OnboardingAction()
- data class UpdateUseCase(val useCase: FtueUseCase) : OnboardingAction()
- object ResetUseCase : OnboardingAction()
- data class UpdateSignMode(val signMode: SignMode) : OnboardingAction()
- data class LoginWithToken(val loginToken: String) : OnboardingAction()
- data class WebLoginSuccess(val credentials: Credentials) : OnboardingAction()
- data class InitWith(val loginConfig: LoginConfig?) : OnboardingAction()
- data class ResetPassword(val email: String, val newPassword: String) : OnboardingAction()
- object ResetPasswordMailConfirmed : OnboardingAction()
+ data class UpdateServerType(val serverType: ServerType) : OnboardingAction
+ data class UpdateHomeServer(val homeServerUrl: String) : OnboardingAction
+ data class UpdateUseCase(val useCase: FtueUseCase) : OnboardingAction
+ object ResetUseCase : OnboardingAction
+ data class UpdateSignMode(val signMode: SignMode) : OnboardingAction
+ data class LoginWithToken(val loginToken: String) : OnboardingAction
+ data class WebLoginSuccess(val credentials: Credentials) : OnboardingAction
+ data class InitWith(val loginConfig: LoginConfig?) : OnboardingAction
+ data class ResetPassword(val email: String, val newPassword: String) : OnboardingAction
+ object ResetPasswordMailConfirmed : OnboardingAction
// Login or Register, depending on the signMode
- data class LoginOrRegister(val username: String, val password: String, val initialDeviceName: String) : OnboardingAction()
+ data class LoginOrRegister(val username: String, val password: String, val initialDeviceName: String) : OnboardingAction
+ object StopEmailValidationCheck : OnboardingAction
- // Register actions
- open class RegisterAction : OnboardingAction()
-
- data class AddThreePid(val threePid: RegisterThreePid) : RegisterAction()
- object SendAgainThreePid : RegisterAction()
-
- // TODO Confirm Email (from link in the email, open in the phone, intercepted by the app)
- data class ValidateThreePid(val code: String) : RegisterAction()
-
- data class CheckIfEmailHasBeenValidated(val delayMillis: Long) : RegisterAction()
- object StopEmailValidationCheck : RegisterAction()
-
- data class CaptchaDone(val captchaResponse: String) : RegisterAction()
- object AcceptTerms : RegisterAction()
- object RegisterDummy : RegisterAction()
+ data class PostRegisterAction(val registerAction: RegisterAction) : OnboardingAction
// Reset actions
- open class ResetAction : OnboardingAction()
+ sealed interface ResetAction : OnboardingAction
- object ResetHomeServerType : ResetAction()
- object ResetHomeServerUrl : ResetAction()
- object ResetSignMode : ResetAction()
- object ResetLogin : ResetAction()
- object ResetResetPassword : ResetAction()
+ object ResetHomeServerType : ResetAction
+ object ResetHomeServerUrl : ResetAction
+ object ResetSignMode : ResetAction
+ object ResetLogin : ResetAction
+ object ResetResetPassword : ResetAction
// Homeserver history
- object ClearHomeServerHistory : OnboardingAction()
+ object ClearHomeServerHistory : OnboardingAction
- data class PostViewEvent(val viewEvent: OnboardingViewEvents) : OnboardingAction()
+ data class PostViewEvent(val viewEvent: OnboardingViewEvents) : OnboardingAction
- data class UserAcceptCertificate(val fingerprint: Fingerprint) : OnboardingAction()
+ data class UserAcceptCertificate(val fingerprint: Fingerprint) : OnboardingAction
- object PersonalizeProfile : OnboardingAction()
- data class UpdateDisplayName(val displayName: String) : OnboardingAction()
- object UpdateDisplayNameSkipped : OnboardingAction()
- data class ProfilePictureSelected(val uri: Uri) : OnboardingAction()
- object SaveSelectedProfilePicture : OnboardingAction()
- object UpdateProfilePictureSkipped : OnboardingAction()
+ object PersonalizeProfile : OnboardingAction
+ data class UpdateDisplayName(val displayName: String) : OnboardingAction
+ object UpdateDisplayNameSkipped : OnboardingAction
+ data class ProfilePictureSelected(val uri: Uri) : OnboardingAction
+ object SaveSelectedProfilePicture : OnboardingAction
+ object UpdateProfilePictureSkipped : OnboardingAction
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt
index 36020fbe61..e7302cb1e2 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt
@@ -31,7 +31,6 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.configureAndStart
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.vectorStore
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -83,6 +82,7 @@ class OnboardingViewModel @AssistedInject constructor(
private val vectorFeatures: VectorFeatures,
private val analyticsTracker: AnalyticsTracker,
private val uriFilenameResolver: UriFilenameResolver,
+ private val registrationActionHandler: RegistrationActionHandler,
private val vectorOverrides: VectorOverrides
) : VectorViewModel(initialState) {
@@ -116,16 +116,16 @@ class OnboardingViewModel @AssistedInject constructor(
private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
+ private val registrationWizard: RegistrationWizard
+ get() = authenticationService.getRegistrationWizard()
+
val currentThreePid: String?
- get() = registrationWizard?.currentThreePid
+ get() = registrationWizard.currentThreePid
// True when login and password has been sent with success to the homeserver
val isRegistrationStarted: Boolean
get() = authenticationService.isRegistrationStarted
- private val registrationWizard: RegistrationWizard?
- get() = authenticationService.getRegistrationWizard()
-
private val loginWizard: LoginWizard?
get() = authenticationService.getLoginWizard()
@@ -153,7 +153,7 @@ class OnboardingViewModel @AssistedInject constructor(
is OnboardingAction.WebLoginSuccess -> handleWebLoginSuccess(action)
is OnboardingAction.ResetPassword -> handleResetPassword(action)
is OnboardingAction.ResetPasswordMailConfirmed -> handleResetPasswordMailConfirmed()
- is OnboardingAction.RegisterAction -> handleRegisterAction(action)
+ is OnboardingAction.PostRegisterAction -> handleRegisterAction(action.registerAction)
is OnboardingAction.ResetAction -> handleResetAction(action)
is OnboardingAction.UserAcceptCertificate -> handleUserAcceptCertificate(action)
OnboardingAction.ClearHomeServerHistory -> handleClearHomeServerHistory()
@@ -164,7 +164,8 @@ class OnboardingViewModel @AssistedInject constructor(
is OnboardingAction.ProfilePictureSelected -> handleProfilePictureSelected(action)
OnboardingAction.SaveSelectedProfilePicture -> updateProfilePicture()
is OnboardingAction.PostViewEvent -> _viewEvents.post(action.viewEvent)
- }.exhaustive
+ OnboardingAction.StopEmailValidationCheck -> cancelWaitForEmailValidation()
+ }
}
private fun handleSplashAction(resetConfig: Boolean, onboardingFlow: OnboardingFlow) {
@@ -220,6 +221,7 @@ class OnboardingViewModel @AssistedInject constructor(
.withAllowedFingerPrints(listOf(action.fingerprint))
.build()
)
+ else -> Unit
}
}
@@ -266,131 +268,41 @@ class OnboardingViewModel @AssistedInject constructor(
}
}
- private fun handleRegisterAction(action: OnboardingAction.RegisterAction) {
- when (action) {
- is OnboardingAction.CaptchaDone -> handleCaptchaDone(action)
- is OnboardingAction.AcceptTerms -> handleAcceptTerms()
- is OnboardingAction.RegisterDummy -> handleRegisterDummy()
- is OnboardingAction.AddThreePid -> handleAddThreePid(action)
- is OnboardingAction.SendAgainThreePid -> handleSendAgainThreePid()
- is OnboardingAction.ValidateThreePid -> handleValidateThreePid(action)
- is OnboardingAction.CheckIfEmailHasBeenValidated -> handleCheckIfEmailHasBeenValidated(action)
- is OnboardingAction.StopEmailValidationCheck -> handleStopEmailValidationCheck()
- }
- }
-
- private fun handleCheckIfEmailHasBeenValidated(action: OnboardingAction.CheckIfEmailHasBeenValidated) {
- // We do not want the common progress bar to be displayed, so we do not change asyncRegistration value in the state
- currentJob = executeRegistrationStep(withLoading = false) {
- it.checkIfEmailHasBeenValidated(action.delayMillis)
- }
- }
-
- private fun handleStopEmailValidationCheck() {
- currentJob = null
- }
-
- private fun handleValidateThreePid(action: OnboardingAction.ValidateThreePid) {
- currentJob = executeRegistrationStep {
- it.handleValidateThreePid(action.code)
- }
- }
-
- private fun executeRegistrationStep(withLoading: Boolean = true,
- block: suspend (RegistrationWizard) -> RegistrationResult): Job {
- if (withLoading) {
- setState { copy(asyncRegistration = Loading()) }
- }
- return viewModelScope.launch {
- try {
- registrationWizard?.let { block(it) }
- /*
- // Simulate registration disabled
- throw Failure.ServerError(MatrixError(
- code = MatrixError.FORBIDDEN,
- message = "Registration is disabled"
- ), 403))
- */
- } catch (failure: Throwable) {
- if (failure !is CancellationException) {
- _viewEvents.post(OnboardingViewEvents.Failure(failure))
- }
- null
- }
- ?.let { data ->
- when (data) {
- is RegistrationResult.Success -> onSessionCreated(data.session, isAccountCreated = true)
- is RegistrationResult.FlowResponse -> onFlowResponse(data.flowResult)
- }
- }
-
- setState {
- copy(
- asyncRegistration = Uninitialized
- )
- }
- }
- }
-
- private fun handleAddThreePid(action: OnboardingAction.AddThreePid) {
- setState { copy(asyncRegistration = Loading()) }
+ private fun handleRegisterAction(action: RegisterAction) {
currentJob = viewModelScope.launch {
- try {
- registrationWizard?.addThreePid(action.threePid)
- } catch (failure: Throwable) {
- _viewEvents.post(OnboardingViewEvents.Failure(failure))
+ if (action.hasLoadingState()) {
+ setState { copy(asyncRegistration = Loading()) }
}
- setState {
- copy(
- asyncRegistration = Uninitialized
- )
- }
- }
- }
-
- private fun handleSendAgainThreePid() {
- setState { copy(asyncRegistration = Loading()) }
- currentJob = viewModelScope.launch {
- try {
- registrationWizard?.sendAgainThreePid()
- } catch (failure: Throwable) {
- _viewEvents.post(OnboardingViewEvents.Failure(failure))
- }
- setState {
- copy(
- asyncRegistration = Uninitialized
- )
- }
- }
- }
-
- private fun handleAcceptTerms() {
- currentJob = executeRegistrationStep {
- it.acceptTerms()
- }
- }
-
- private fun handleRegisterDummy() {
- currentJob = executeRegistrationStep {
- it.dummy()
+ runCatching { registrationActionHandler.handleRegisterAction(registrationWizard, action) }
+ .fold(
+ onSuccess = {
+ when {
+ action.ignoresResult() -> {
+ // do nothing
+ }
+ else -> when (it) {
+ is RegistrationResult.Success -> onSessionCreated(it.session, isAccountCreated = true)
+ is RegistrationResult.FlowResponse -> onFlowResponse(it.flowResult)
+ }
+ }
+ },
+ onFailure = {
+ if (it !is CancellationException) {
+ _viewEvents.post(OnboardingViewEvents.Failure(it))
+ }
+ }
+ )
+ setState { copy(asyncRegistration = Uninitialized) }
}
}
private fun handleRegisterWith(action: OnboardingAction.LoginOrRegister) {
reAuthHelper.data = action.password
- currentJob = executeRegistrationStep {
- it.createAccount(
- action.username,
- action.password,
- action.initialDeviceName
- )
- }
- }
-
- private fun handleCaptchaDone(action: OnboardingAction.CaptchaDone) {
- currentJob = executeRegistrationStep {
- it.performReCaptcha(action.captchaResponse)
- }
+ handleRegisterAction(RegisterAction.CreateAccount(
+ action.username,
+ action.password,
+ action.initialDeviceName
+ ))
}
private fun handleResetAction(action: OnboardingAction.ResetAction) {
@@ -461,7 +373,7 @@ class OnboardingViewModel @AssistedInject constructor(
}
when (action.signMode) {
- SignMode.SignUp -> startRegistrationFlow()
+ SignMode.SignUp -> handleRegisterAction(RegisterAction.StartRegistration)
SignMode.SignIn -> startAuthenticationFlow()
SignMode.SignInWithMatrixId -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.SignInWithMatrixId))
SignMode.Unknown -> Unit
@@ -491,7 +403,7 @@ class OnboardingViewModel @AssistedInject constructor(
handle(OnboardingAction.UpdateHomeServer(matrixOrgUrl))
ServerType.EMS,
ServerType.Other -> _viewEvents.post(OnboardingViewEvents.OnServerSelectionDone(action.serverType))
- }.exhaustive
+ }
}
private fun handleInitWith(action: OnboardingAction.InitWith) {
@@ -499,7 +411,7 @@ class OnboardingViewModel @AssistedInject constructor(
// If there is a pending email validation continue on this step
try {
- if (registrationWizard?.isRegistrationStarted == true) {
+ if (registrationWizard.isRegistrationStarted) {
currentThreePid?.let {
handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnSendEmailSuccess(it)))
}
@@ -599,7 +511,7 @@ class OnboardingViewModel @AssistedInject constructor(
SignMode.SignIn -> handleLogin(action)
SignMode.SignUp -> handleRegisterWith(action)
SignMode.SignInWithMatrixId -> handleDirectLogin(action, null)
- }.exhaustive
+ }
}
private fun handleDirectLogin(action: OnboardingAction.LoginOrRegister, homeServerConnectionConfig: HomeServerConnectionConfig?) {
@@ -629,7 +541,7 @@ class OnboardingViewModel @AssistedInject constructor(
else -> {
onWellKnownError()
}
- }.exhaustive
+ }
}
}
@@ -730,12 +642,6 @@ class OnboardingViewModel @AssistedInject constructor(
}
}
- private fun startRegistrationFlow() {
- currentJob = executeRegistrationStep {
- it.getRegistrationFlow()
- }
- }
-
private fun startAuthenticationFlow() {
// Ensure Wizard is ready
loginWizard
@@ -745,8 +651,7 @@ class OnboardingViewModel @AssistedInject constructor(
private fun onFlowResponse(flowResult: FlowResult) {
// If dummy stage is mandatory, and password is already sent, do the dummy stage now
- if (isRegistrationStarted &&
- flowResult.missingStages.any { it is Stage.Dummy && it.mandatory }) {
+ if (isRegistrationStarted && flowResult.missingStages.any { it is Stage.Dummy && it.mandatory }) {
handleRegisterDummy()
} else {
// Notify the user
@@ -754,6 +659,10 @@ class OnboardingViewModel @AssistedInject constructor(
}
}
+ private fun handleRegisterDummy() {
+ handleRegisterAction(RegisterAction.RegisterDummy)
+ }
+
private suspend fun onSessionCreated(session: Session, isAccountCreated: Boolean) {
val state = awaitState()
state.useCase?.let { useCase ->
@@ -1006,6 +915,10 @@ class OnboardingViewModel @AssistedInject constructor(
private fun completePersonalization() {
_viewEvents.post(OnboardingViewEvents.OnPersonalizationComplete)
}
+
+ private fun cancelWaitForEmailValidation() {
+ currentJob = null
+ }
}
private fun LoginMode.supportsSignModeScreen(): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt b/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt
new file mode 100644
index 0000000000..b4998d2ba0
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/onboarding/RegistrationActionHandler.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.onboarding
+
+import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
+import javax.inject.Inject
+
+class RegistrationActionHandler @Inject constructor() {
+
+ suspend fun handleRegisterAction(registrationWizard: RegistrationWizard, action: RegisterAction): RegistrationResult {
+ return when (action) {
+ RegisterAction.StartRegistration -> registrationWizard.getRegistrationFlow()
+ is RegisterAction.CaptchaDone -> registrationWizard.performReCaptcha(action.captchaResponse)
+ is RegisterAction.AcceptTerms -> registrationWizard.acceptTerms()
+ is RegisterAction.RegisterDummy -> registrationWizard.dummy()
+ is RegisterAction.AddThreePid -> registrationWizard.addThreePid(action.threePid)
+ is RegisterAction.SendAgainThreePid -> registrationWizard.sendAgainThreePid()
+ is RegisterAction.ValidateThreePid -> registrationWizard.handleValidateThreePid(action.code)
+ is RegisterAction.CheckIfEmailHasBeenValidated -> registrationWizard.checkIfEmailHasBeenValidated(action.delayMillis)
+ is RegisterAction.CreateAccount -> registrationWizard.createAccount(action.username, action.password, action.initialDeviceName)
+ }
+ }
+}
+
+sealed interface RegisterAction {
+ object StartRegistration : RegisterAction
+ data class CreateAccount(val username: String, val password: String, val initialDeviceName: String) : RegisterAction
+
+ data class AddThreePid(val threePid: RegisterThreePid) : RegisterAction
+ object SendAgainThreePid : RegisterAction
+
+ // TODO Confirm Email (from link in the email, open in the phone, intercepted by the app)
+ data class ValidateThreePid(val code: String) : RegisterAction
+
+ data class CheckIfEmailHasBeenValidated(val delayMillis: Long) : RegisterAction
+
+ data class CaptchaDone(val captchaResponse: String) : RegisterAction
+ object AcceptTerms : RegisterAction
+ object RegisterDummy : RegisterAction
+}
+
+fun RegisterAction.ignoresResult() = when (this) {
+ is RegisterAction.AddThreePid -> true
+ is RegisterAction.SendAgainThreePid -> true
+ else -> false
+}
+
+fun RegisterAction.hasLoadingState() = when (this) {
+ is RegisterAction.CheckIfEmailHasBeenValidated -> false
+ else -> true
+}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt
index 0caf2ea152..f8f6f6cefa 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractFtueAuthFragment.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.features.onboarding.OnboardingAction
@@ -73,7 +72,7 @@ abstract class AbstractFtueAuthFragment : VectorBaseFragment
// This is handled by the Activity
Unit
- }.exhaustive
+ }
}
override fun showFailure(throwable: Throwable) {
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt
index e2e390ae2d..4773332138 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt
@@ -39,6 +39,7 @@ import im.vector.app.databinding.FragmentLoginCaptchaBinding
import im.vector.app.features.login.JavascriptResponse
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewState
+import im.vector.app.features.onboarding.RegisterAction
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.internal.di.MoshiProvider
import timber.log.Timber
@@ -181,7 +182,7 @@ class FtueAuthCaptchaFragment @Inject constructor(
val response = javascriptResponse?.response
if (javascriptResponse?.action == "verifyCallback" && response != null) {
- viewModel.handle(OnboardingAction.CaptchaDone(response))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CaptchaDone(response)))
}
}
return true
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthGenericTextInputFormFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthGenericTextInputFormFragment.kt
index bd5054f646..2800530152 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthGenericTextInputFormFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthGenericTextInputFormFragment.kt
@@ -37,6 +37,7 @@ import im.vector.app.databinding.FragmentLoginGenericTextInputFormBinding
import im.vector.app.features.login.TextInputFormFragmentMode
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewEvents
+import im.vector.app.features.onboarding.RegisterAction
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize
@@ -138,7 +139,7 @@ class FtueAuthGenericTextInputFormFragment @Inject constructor() : AbstractFtueA
private fun onOtherButtonClicked() {
when (params.mode) {
TextInputFormFragmentMode.ConfirmMsisdn -> {
- viewModel.handle(OnboardingAction.SendAgainThreePid)
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.SendAgainThreePid))
}
else -> {
// Should not happen, button is not displayed
@@ -152,19 +153,19 @@ class FtueAuthGenericTextInputFormFragment @Inject constructor() : AbstractFtueA
if (text.isEmpty()) {
// Perform dummy action
- viewModel.handle(OnboardingAction.RegisterDummy)
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.RegisterDummy))
} else {
when (params.mode) {
TextInputFormFragmentMode.SetEmail -> {
- viewModel.handle(OnboardingAction.AddThreePid(RegisterThreePid.Email(text)))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AddThreePid(RegisterThreePid.Email(text))))
}
TextInputFormFragmentMode.SetMsisdn -> {
getCountryCodeOrShowError(text)?.let { countryCode ->
- viewModel.handle(OnboardingAction.AddThreePid(RegisterThreePid.Msisdn(text, countryCode)))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AddThreePid(RegisterThreePid.Msisdn(text, countryCode))))
}
}
TextInputFormFragmentMode.ConfirmMsisdn -> {
- viewModel.handle(OnboardingAction.ValidateThreePid(text))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.ValidateThreePid(text)))
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt
index 5f15d9a35d..dacd8feab3 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt
@@ -28,9 +28,7 @@ import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
-import com.airbnb.mvrx.Success
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.hidePassword
import im.vector.app.core.extensions.toReducedUrl
@@ -105,7 +103,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
views.loginField.setAutofillHints(HintConstants.AUTOFILL_HINT_USERNAME)
views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_PASSWORD)
}
- }.exhaustive
+ }
}
}
@@ -115,7 +113,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
SignMode.SignUp -> SocialLoginButtonsView.Mode.MODE_SIGN_UP
SignMode.SignIn,
SignMode.SignInWithMatrixId -> SocialLoginButtonsView.Mode.MODE_SIGN_IN
- }.exhaustive
+ }
}
private fun submit() {
@@ -299,7 +297,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
}
}
// Success is handled by the LoginActivity
- is Success -> Unit
+ else -> Unit
}
when (state.asyncRegistration) {
@@ -308,7 +306,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment<
views.passwordField.hidePassword()
}
// Success is handled by the LoginActivity
- is Success -> Unit
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt
index 6a224dfae8..073801c920 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt
@@ -23,7 +23,6 @@ import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
-import com.airbnb.mvrx.Success
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
@@ -125,7 +124,7 @@ class FtueAuthResetPasswordFragment @Inject constructor() : AbstractFtueAuthFrag
is Fail -> {
views.resetPasswordEmailTil.error = errorFormatter.toHumanReadable(state.asyncResetPassword.error)
}
- is Success -> Unit
+ else -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt
index 1d5e1aa00a..f8b3266d37 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordMailConfirmationFragment.kt
@@ -21,7 +21,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Success
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.databinding.FragmentLoginResetPasswordMailConfirmationBinding
@@ -61,7 +60,7 @@ class FtueAuthResetPasswordMailConfirmationFragment @Inject constructor() : Abst
setupUi(state)
when (state.asyncResetMailConfirmed) {
- is Fail -> {
+ is Fail -> {
// Link in email not yet clicked ?
val message = if (state.asyncResetMailConfirmed.error.is401()) {
getString(R.string.auth_reset_password_error_unauthorized)
@@ -75,7 +74,7 @@ class FtueAuthResetPasswordMailConfirmationFragment @Inject constructor() : Abst
.setPositiveButton(R.string.ok, null)
.show()
}
- is Success -> Unit
+ else -> Unit
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt
index 79a974038b..13b5f61010 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt
@@ -31,7 +31,6 @@ import im.vector.app.R
import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.popBackstack
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.ScreenOrientationLocker
@@ -229,7 +228,7 @@ class FtueAuthVariant(
OnboardingViewEvents.OnChooseProfilePicture -> onChooseProfilePicture()
OnboardingViewEvents.OnPersonalizationComplete -> onPersonalizationComplete()
OnboardingViewEvents.OnBack -> activity.popBackstack()
- }.exhaustive
+ }
}
private fun registrationShouldFallback(registrationFlowResult: OnboardingViewEvents.RegistrationFlowResult) =
@@ -281,7 +280,7 @@ class FtueAuthVariant(
SignMode.SignUp -> Unit // This case is processed in handleOnboardingViewEvents
SignMode.SignIn -> handleSignInSelected(state)
SignMode.SignInWithMatrixId -> handleSignInWithMatrixId(state)
- }.exhaustive
+ }
}
private fun handleSignInSelected(state: OnboardingViewState) {
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt
index 94758c7fad..ec72f52b9e 100644
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt
@@ -25,6 +25,7 @@ import com.airbnb.mvrx.args
import im.vector.app.R
import im.vector.app.databinding.FragmentLoginWaitForEmailBinding
import im.vector.app.features.onboarding.OnboardingAction
+import im.vector.app.features.onboarding.RegisterAction
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.failure.is401
import javax.inject.Inject
@@ -54,7 +55,7 @@ class FtueAuthWaitForEmailFragment @Inject constructor() : AbstractFtueAuthFragm
override fun onResume() {
super.onResume()
- viewModel.handle(OnboardingAction.CheckIfEmailHasBeenValidated(0))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CheckIfEmailHasBeenValidated(0)))
}
override fun onPause() {
@@ -70,7 +71,7 @@ class FtueAuthWaitForEmailFragment @Inject constructor() : AbstractFtueAuthFragm
override fun onError(throwable: Throwable) {
if (throwable.is401()) {
// Try again, with a delay
- viewModel.handle(OnboardingAction.CheckIfEmailHasBeenValidated(10_000))
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CheckIfEmailHasBeenValidated(10_000)))
} else {
super.onError(throwable)
}
diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt
index 5ce9a5350d..03598d3a47 100755
--- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt
@@ -32,6 +32,7 @@ import im.vector.app.features.login.terms.LoginTermsViewState
import im.vector.app.features.login.terms.PolicyController
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewState
+import im.vector.app.features.onboarding.RegisterAction
import im.vector.app.features.onboarding.ftueauth.AbstractFtueAuthFragment
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms
@@ -111,7 +112,7 @@ class FtueAuthTermsFragment @Inject constructor(
}
private fun submit() {
- viewModel.handle(OnboardingAction.AcceptTerms)
+ viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AcceptTerms))
}
override fun updateWithState(state: OnboardingViewState) {
diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt
index 4483b00158..2abff7f22b 100644
--- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollFragment.kt
@@ -27,7 +27,6 @@ import com.airbnb.mvrx.args
import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentCreatePollBinding
import im.vector.app.features.poll.create.CreatePollViewModel.Companion.MAX_OPTIONS_COUNT
@@ -68,7 +67,7 @@ class CreatePollFragment @Inject constructor(
views.createPollToolbar.title = getString(R.string.edit_poll_title)
views.createPollButton.text = getString(R.string.edit_poll_title)
}
- }.exhaustive
+ }
views.createPollRecyclerView.configureWith(controller, disableItemAnimation = true)
// workaround for https://github.com/vector-im/element-android/issues/4735
diff --git a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt
index dda7b2e2eb..b23f2f171d 100644
--- a/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/qrcode/QrCodeScannerActivity.kt
@@ -24,7 +24,6 @@ import androidx.activity.result.ActivityResultLauncher
import com.airbnb.mvrx.viewModel
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
@@ -51,7 +50,7 @@ class QrCodeScannerActivity() : VectorBaseActivity() {
finish()
}
else -> Unit
- }.exhaustive
+ }
}
if (isFirstCreation()) {
diff --git a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt
index a77bd32f26..0cb49746f1 100644
--- a/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/room/RequireActiveMembershipViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-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
@@ -127,6 +126,6 @@ class RequireActiveMembershipViewModel @AssistedInject constructor(
}
roomIdFlow.tryEmit(Optional.from(action.roomId))
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
index 14b50c2745..b8bba347fd 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
@@ -28,7 +28,6 @@ import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.trackItemsVisibilityChange
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.showOptimizedSnackbar
@@ -96,7 +95,7 @@ class PublicRoomsFragment @Inject constructor(
is RoomDirectoryViewEvents.Failure -> {
views.coordinatorLayout.showOptimizedSnackbar(errorFormatter.toHumanReadable(viewEvents.throwable))
}
- }.exhaustive
+ }
}
override fun onDestroyView() {
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryActivity.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryActivity.kt
index 48da9f4fa0..f0df31342e 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/RoomDirectoryActivity.kt
@@ -62,8 +62,8 @@ class RoomDirectoryActivity : VectorBaseActivity(), Matri
.stream()
.onEach { sharedAction ->
when (sharedAction) {
- is RoomDirectorySharedAction.Back -> popBackstack()
- is RoomDirectorySharedAction.CreateRoom -> {
+ is RoomDirectorySharedAction.Back -> popBackstack()
+ is RoomDirectorySharedAction.CreateRoom -> {
// Transmit the filter to the CreateRoomFragment
withState(roomDirectoryViewModel) {
addFragmentToBackstack(
@@ -73,9 +73,10 @@ class RoomDirectoryActivity : VectorBaseActivity(), Matri
)
}
}
- is RoomDirectorySharedAction.ChangeProtocol ->
+ is RoomDirectorySharedAction.ChangeProtocol ->
addFragmentToBackstack(views.simpleFragmentContainer, RoomDirectoryPickerFragment::class.java)
- is RoomDirectorySharedAction.Close -> finish()
+ is RoomDirectorySharedAction.Close -> finish()
+ is RoomDirectorySharedAction.CreateRoomSuccess -> Unit
}
}
.launchIn(lifecycleScope)
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt
index 2bd41ae3af..2871513c1f 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomFragment.kt
@@ -34,7 +34,6 @@ import im.vector.app.R
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.ColorProvider
@@ -94,7 +93,7 @@ class CreateRoomFragment @Inject constructor(
when (it) {
CreateRoomViewEvents.Quit -> vectorBaseActivity.onBackPressed()
is CreateRoomViewEvents.Failure -> showFailure(it.throwable)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt
index 3b2e9de2d1..7d65c44a57 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt
@@ -28,7 +28,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.AppStateHandler
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.plan.CreatedRoom
@@ -138,7 +137,7 @@ class CreateRoomViewModel @AssistedInject constructor(
CreateRoomAction.Reset -> doReset()
CreateRoomAction.ToggleShowAdvanced -> toggleShowAdvanced()
is CreateRoomAction.DisableFederation -> disableFederation(action)
- }.exhaustive
+ }
}
private fun disableFederation(action: CreateRoomAction.DisableFederation) {
@@ -281,7 +280,7 @@ class CreateRoomViewModel @AssistedInject constructor(
// Preset
preset = CreateRoomPreset.PRESET_PRIVATE_CHAT
}
- }.exhaustive
+ }
// Disabling federation
disableFederation = state.disableFederation
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt
index 08e044630d..7d121d1ff4 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerController.kt
@@ -22,7 +22,6 @@ import android.view.inputmethod.EditorInfo
import android.widget.TextView
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
@@ -60,7 +59,7 @@ class RoomDirectoryPickerController @Inject constructor(
val host = this
when (val asyncThirdPartyProtocol = data.asyncThirdPartyRequest) {
- is Success -> {
+ is Success -> {
data.directories.join(
each = { _, roomDirectoryServer -> buildDirectory(roomDirectoryServer) },
between = { idx, _ -> buildDivider(idx) }
@@ -71,12 +70,13 @@ class RoomDirectoryPickerController @Inject constructor(
heightInPx(host.dimensionConverter.dpToPx(16))
}
}
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("loading")
}
}
- is Fail -> {
+ is Fail -> {
errorWithRetryItem {
id("error")
text(host.errorFormatter.toHumanReadable(asyncThirdPartyProtocol.error))
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
index a5673e78a2..51af9a8286 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/picker/RoomDirectoryPickerViewModel.kt
@@ -27,7 +27,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -104,7 +103,7 @@ class RoomDirectoryPickerViewModel @AssistedInject constructor(
is RoomDirectoryPickerAction.SetServerUrl -> handleSetServerUrl(action)
RoomDirectoryPickerAction.Submit -> handleSubmit()
is RoomDirectoryPickerAction.RemoveServer -> handleRemoveServer(action)
- }.exhaustive
+ }
}
private fun handleEnterEditMode() {
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
index 42bec8c8b3..a22dc7ed95 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/roompreview/RoomPreviewViewModel.kt
@@ -24,7 +24,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
@@ -204,7 +203,7 @@ class RoomPreviewViewModel @AssistedInject constructor(
when (action) {
is RoomPreviewAction.Join -> handleJoinRoom()
RoomPreviewAction.JoinThirdParty -> handleJoinRoomThirdParty()
- }.exhaustive
+ }
}
private fun handleJoinRoomThirdParty() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt
index 7e919fb663..d9ed6d227a 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt
@@ -25,8 +25,9 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
@@ -38,7 +39,6 @@ import im.vector.app.core.dialogs.ConfirmationDialogBuilder
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.copyOnLongClick
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.StateView
import im.vector.app.core.platform.VectorBaseFragment
@@ -133,7 +133,7 @@ class RoomMemberProfileFragment @Inject constructor(
is RoomMemberProfileViewEvents.OnBanActionSuccess -> Unit
is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit
is RoomMemberProfileViewEvents.OnInviteActionSuccess -> Unit
- }.exhaustive
+ }
}
setupLongClicks()
}
@@ -198,18 +198,19 @@ class RoomMemberProfileFragment @Inject constructor(
override fun invalidate() = withState(viewModel) { state ->
when (val asyncUserMatrixItem = state.userMatrixItem) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
views.matrixProfileToolbarTitleView.text = state.userId
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), views.matrixProfileToolbarAvatarImageView)
headerViews.memberProfileStateView.state = StateView.State.Loading
}
- is Fail -> {
+ is Fail -> {
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), views.matrixProfileToolbarAvatarImageView)
views.matrixProfileToolbarTitleView.text = state.userId
val failureMessage = errorFormatter.toHumanReadable(asyncUserMatrixItem.error)
headerViews.memberProfileStateView.state = StateView.State.Error(failureMessage)
}
- is Success -> {
+ is Success -> {
val userMatrixItem = asyncUserMatrixItem()
headerViews.memberProfileStateView.state = StateView.State.Content
headerViews.memberProfileIdView.text = userMatrixItem.id
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt
index a79a9f4c1d..db54f27910 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt
@@ -28,7 +28,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -170,7 +169,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
RoomMemberProfileAction.InviteUser -> handleInviteAction()
is RoomMemberProfileAction.SetUserColorOverride -> handleSetUserColorOverride(action)
is RoomMemberProfileAction.OpenOrCreateDm -> handleOpenOrCreateDm(action)
- }.exhaustive
+ }
}
private fun handleOpenOrCreateDm(action: RoomMemberProfileAction.OpenOrCreateDm) {
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
index bb2317b59c..8df0b3ffd5 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheet.kt
@@ -29,7 +29,6 @@ import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.commitTransaction
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetWithFragmentsBinding
import im.vector.app.features.crypto.verification.VerificationBottomSheet
@@ -57,7 +56,7 @@ class DeviceListBottomSheet :
transactionId = it.txID
).show(requireActivity().supportFragmentManager, "REQPOP")
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
index d2491237ca..03e07a2f82 100644
--- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt
@@ -28,7 +28,6 @@ import dagger.hilt.EntryPoints
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.SingletonEntryPoint
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@@ -94,7 +93,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
is DeviceListAction.SelectDevice -> selectDevice(action)
is DeviceListAction.DeselectDevice -> deselectDevice()
is DeviceListAction.ManuallyVerify -> manuallyVerify(action)
- }.exhaustive
+ }
}
private fun refreshSelectedId() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
index 4c6d2ed2e3..12a5d94eca 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileActivity.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.viewModel
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
@@ -102,7 +101,7 @@ class RoomProfileActivity :
RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
RoomProfileSharedAction.OpenRoomNotificationSettings -> openRoomNotificationSettings()
- }.exhaustive
+ }
}
.launchIn(lifecycleScope)
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
index b13ef2a5d1..ba9280dc59 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt
@@ -37,7 +37,6 @@ import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.copyOnLongClick
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.copyToClipboard
@@ -127,7 +126,7 @@ class RoomProfileFragment @Inject constructor(
is RoomProfileViewEvents.ShareRoomProfile -> onShareRoomProfile(it.permalink)
is RoomProfileViewEvents.OnShortcutReady -> addShortcut(it)
RoomProfileViewEvents.DismissLoading -> dismissLoadingDialog()
- }.exhaustive
+ }
}
roomListQuickActionsSharedActionViewModel
.stream()
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt
index b7c7d24888..61013c8eb6 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileViewModel.kt
@@ -24,7 +24,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.ShortcutCreator
@@ -137,7 +136,7 @@ class RoomProfileViewModel @AssistedInject constructor(
is RoomProfileAction.ShareRoomProfile -> handleShareRoomProfile()
RoomProfileAction.CreateShortcut -> handleCreateShortcut()
RoomProfileAction.RestoreEncryptionState -> restoreEncryptionState()
- }.exhaustive
+ }
}
fun isPublicRoom(): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt
index 03e6ab9984..fcf6bc3a47 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasController.kt
@@ -199,12 +199,13 @@ class RoomAliasController @Inject constructor(
}
when (val localAliases = data.localAliases) {
- is Uninitialized -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("loadingAliases")
}
}
- is Success -> {
+ is Success -> {
if (localAliases().isEmpty()) {
settingsInfoItem {
id("locEmpty")
@@ -220,7 +221,7 @@ class RoomAliasController @Inject constructor(
}
}
}
- is Fail -> {
+ is Fail -> {
errorWithRetryItem {
id("alt_error")
text(host.errorFormatter.toHumanReadable(localAliases.error))
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt
index e48ce54e6c..2a738fd07c 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasFragment.kt
@@ -29,7 +29,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.shareText
import im.vector.app.core.utils.toast
@@ -77,7 +76,7 @@ class RoomAliasFragment @Inject constructor(
when (it) {
is RoomAliasViewEvents.Failure -> showFailure(it.throwable)
RoomAliasViewEvents.Success -> showSuccess()
- }.exhaustive
+ }
}
sharedActionViewModel
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt
index 19f600e5de..adffbcbd06 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/alias/RoomAliasViewModel.kt
@@ -26,7 +26,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import kotlinx.coroutines.flow.launchIn
@@ -190,7 +189,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
is RoomAliasAction.RemoveLocalAlias -> handleRemoveLocalAlias(action)
is RoomAliasAction.PublishAlias -> handlePublishAlias(action)
RoomAliasAction.Retry -> handleRetry()
- }.exhaustive
+ }
}
private fun handleRetry() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt
index d7efc2fb79..ec249c75ba 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/banned/RoomBannedMemberListViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
@@ -84,7 +83,7 @@ class RoomBannedMemberListViewModel @AssistedInject constructor(@Assisted initia
is RoomBannedMemberListAction.QueryInfo -> onQueryBanInfo(action.roomMemberSummary)
is RoomBannedMemberListAction.UnBanUser -> unBanUser(action.roomMemberSummary)
is RoomBannedMemberListAction.Filter -> handleFilter(action)
- }.exhaustive
+ }
}
private fun handleFilter(action: RoomBannedMemberListAction.Filter) {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt
index 0bbdd87f3e..c9a70fbef8 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
@@ -181,7 +180,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
when (action) {
is RoomMemberListAction.RevokeThreePidInvite -> handleRevokeThreePidInvite(action)
is RoomMemberListAction.FilterMemberList -> handleFilterMemberList(action)
- }.exhaustive
+ }
}
private fun handleRevokeThreePidInvite(action: RoomMemberListAction.RevokeThreePidInvite) {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt
index 0d5ac7dea8..c1175796fb 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsFragment.kt
@@ -27,7 +27,6 @@ import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.toast
import im.vector.app.databinding.FragmentRoomSettingGenericBinding
@@ -67,7 +66,7 @@ class RoomPermissionsFragment @Inject constructor(
when (it) {
is RoomPermissionsViewEvents.Failure -> showFailure(it.throwable)
RoomPermissionsViewEvents.Success -> showSuccess()
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt
index 7e8a66d12a..6fbc545b6c 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import kotlinx.coroutines.flow.launchIn
@@ -90,7 +89,7 @@ class RoomPermissionsViewModel @AssistedInject constructor(@Assisted initialStat
when (action) {
is RoomPermissionsAction.UpdatePermission -> updatePermission(action)
RoomPermissionsAction.ToggleShowAllPermissions -> toggleShowAllPermissions()
- }.exhaustive
+ }
}
private fun toggleShowAllPermissions() {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt
index 51f6b247d4..0bde35f41e 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt
@@ -33,7 +33,6 @@ import im.vector.app.R
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
@@ -98,7 +97,7 @@ class RoomSettingsFragment @Inject constructor(
ignoreChanges = true
vectorBaseActivity.onBackPressed()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt
index a0325cfc2b..8ad5bcdce6 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import im.vector.app.features.settings.VectorPreferences
@@ -201,7 +200,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
is RoomSettingsAction.SetRoomGuestAccess -> handleSetGuestAccess(action)
is RoomSettingsAction.Save -> saveSettings()
is RoomSettingsAction.Cancel -> cancel()
- }.exhaustive
+ }
}
private fun handleSetRoomJoinRule(action: RoomSettingsAction.SetRoomJoinRule) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt
index 548ec9cfe4..f1897761b2 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt
@@ -29,7 +29,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.styleMatchingText
@@ -180,7 +179,7 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
is RoomJoinRuleChooseRestrictedActions.SelectJoinRules -> handleSelectRule(action)
is RoomJoinRuleChooseRestrictedActions.SwitchToRoomAfterMigration -> handleSwitchToRoom(action)
RoomJoinRuleChooseRestrictedActions.DoUpdateJoinRules -> handleSubmit()
- }.exhaustive
+ }
checkForChanges()
}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt
index a0adf42d5b..6a115ad272 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsFragment.kt
@@ -28,7 +28,6 @@ import com.airbnb.mvrx.withState
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayoutMediator
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.saveMedia
@@ -99,7 +98,7 @@ class RoomUploadsFragment @Inject constructor(
Unit
}
is RoomUploadsViewEvents.Failure -> showFailure(it.throwable)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt
index 92ff33395e..c9aaca4373 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/RoomUploadsViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-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
@@ -110,7 +109,7 @@ class RoomUploadsViewModel @AssistedInject constructor(
is RoomUploadsAction.Share -> handleShare(action)
RoomUploadsAction.Retry -> handleLoadMore()
RoomUploadsAction.LoadMore -> handleLoadMore()
- }.exhaustive
+ }
}
private fun handleShare(action: RoomUploadsAction.Share) {
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt
index 1739378761..953838aecd 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/files/RoomUploadsFilesFragment.kt
@@ -24,6 +24,7 @@ import androidx.core.content.ContextCompat
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.parentFragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.R
@@ -91,6 +92,7 @@ class RoomUploadsFilesFragment @Inject constructor(
override fun invalidate() = withState(uploadsViewModel) { state ->
if (state.fileEvents.isEmpty()) {
when (state.asyncEventsRequest) {
+ Uninitialized,
is Loading -> {
views.genericStateViewListStateView.state = StateView.State.Loading
}
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
index eb4337cffa..2f33f8403c 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
@@ -29,6 +29,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.parentFragmentViewModel
import com.airbnb.mvrx.withState
import com.google.android.material.appbar.AppBarLayout
@@ -188,6 +189,7 @@ class RoomUploadsMediaFragment @Inject constructor(
override fun invalidate() = withState(uploadsViewModel) { state ->
if (state.mediaEvents.isEmpty()) {
when (state.asyncEventsRequest) {
+ Uninitialized,
is Loading -> {
views.genericStateViewListStateView.state = StateView.State.Loading
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
index 352c5768fb..8d93edc0ec 100755
--- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt
@@ -201,7 +201,13 @@ class VectorPreferences @Inject constructor(private val context: Context) {
private const val TAKE_PHOTO_VIDEO_MODE = "TAKE_PHOTO_VIDEO_MODE"
private const val SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE = "SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE"
- const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES"
+
+ // This key will be used to identify clients with the old thread support enabled io.element.thread
+ const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES"
+
+ // This key will be used to identify clients with the new thread support enabled m.thread
+ const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES_FINAL"
+ const val SETTINGS_THREAD_MESSAGES_SYNCED = "SETTINGS_THREAD_MESSAGES_SYNCED"
// Possible values for TAKE_PHOTO_VIDEO_MODE
const val TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK = 0
@@ -1006,7 +1012,56 @@ class VectorPreferences @Inject constructor(private val context: Context) {
return defaultPrefs.getBoolean(SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE, true)
}
+ /**
+ * Indicates whether or not thread messages are enabled
+ */
fun areThreadMessagesEnabled(): Boolean {
- return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, false)
+ return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, getDefault(R.bool.settings_labs_thread_messages_default))
+ }
+
+ /**
+ * Manually sets thread messages enabled, useful for migrating users from io.element.thread
+ */
+ fun setThreadMessagesEnabled() {
+ defaultPrefs
+ .edit()
+ .putBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, true)
+ .apply()
+ }
+
+ /**
+ * Indicates whether or not the user will be notified about the new thread support
+ * We should notify the user only if he had old thread support enabled
+ */
+ fun shouldNotifyUserAboutThreads(): Boolean {
+ return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS, false)
+ }
+
+ /**
+ * Indicates that the user have been notified about threads migration
+ */
+ fun userNotifiedAboutThreads() {
+ defaultPrefs
+ .edit()
+ .putBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS, false)
+ .apply()
+ }
+
+ /**
+ * Indicates whether or not we should clear cache for threads migration.
+ * Default value is true, for fresh installs and updates
+ */
+ fun shouldMigrateThreads(): Boolean {
+ return defaultPrefs.getBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, true)
+ }
+
+ /**
+ * Indicates that there no longer threads migration needed
+ */
+ fun setShouldMigrateThreads(shouldMigrate: Boolean) {
+ defaultPrefs
+ .edit()
+ .putBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, shouldMigrate)
+ .apply()
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt
index 118e820f84..003832fb97 100644
--- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt
@@ -42,6 +42,8 @@ class VectorSettingsLabsFragment @Inject constructor(
// clear cache
findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let {
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
+ // We should migrate threads only if threads are disabled
+ vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled())
lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
displayLoadingView()
MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true))
diff --git a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt
index 631c375e62..4397da00c4 100644
--- a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountFragment.kt
@@ -25,7 +25,6 @@ import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.mvrx.fragmentViewModel
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentDeactivateAccountBinding
@@ -128,7 +127,7 @@ class DeactivateAccountFragment @Inject constructor() : VectorBaseFragment {
views.waitingView.waitingView.isVisible = false
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt
index 644b7f33dd..5e691f64b2 100644
--- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt
@@ -22,7 +22,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
@@ -146,7 +145,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
uiaContinuation = null
pendingAuth = null
}
- }.exhaustive
+ }
}
private fun handleInitializeXSigningError(failure: Throwable) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt
index 5bbb03c8a4..407af19151 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt
@@ -32,7 +32,6 @@ import im.vector.app.R
import im.vector.app.core.dialogs.ManuallyVerifyDialog
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.DialogBaseEditTextBinding
@@ -90,7 +89,7 @@ class VectorSettingsDevicesFragment @Inject constructor(
viewModel.handle(DevicesAction.MarkAsManuallyVerified(it.cryptoDeviceInfo))
}
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt
index f3ae18a72f..4748aeb45e 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt
@@ -21,6 +21,7 @@ import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.resources.StringProvider
@@ -45,6 +46,7 @@ class AccountDataEpoxyController @Inject constructor(
if (data == null) return
val host = this
when (data.accountData) {
+ Uninitialized,
is Loading -> {
loadingItem {
id("loading")
diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt
index 6289699687..9576b84e98 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch
@@ -51,7 +50,7 @@ class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: A
override fun handle(action: AccountDataAction) {
when (action) {
is AccountDataAction.DeleteAccountData -> handleDeleteAccountData(action)
- }.exhaustive
+ }
}
private fun handleDeleteAccountData(action: AccountDataAction.DeleteAccountData) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt
index f480eb2db8..fd1cd3480d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestViewModel.kt
@@ -29,7 +29,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
@@ -64,7 +63,7 @@ class KeyRequestViewModel @AssistedInject constructor(
override fun handle(action: KeyRequestAction) {
when (action) {
is KeyRequestAction.ExportAudit -> exportAudit(action)
- }.exhaustive
+ }
}
private fun exportAudit(action: KeyRequestAction.ExportAudit) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt
index d807fc620a..db2d07feef 100644
--- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt
@@ -33,7 +33,6 @@ import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.google.android.material.tabs.TabLayoutMediator
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.selectTxtFileToWrite
@@ -111,7 +110,7 @@ class KeyRequestsFragment @Inject constructor() : VectorBaseFragment os.write(it.raw.toByteArray()) }
}
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt
index 509014492d..5c188fe933 100644
--- a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt
@@ -30,7 +30,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentGenericRecyclerBinding
import javax.inject.Inject
@@ -57,7 +56,7 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor(
when (it) {
is IgnoredUsersViewEvents.Loading -> showLoading(it.message)
is IgnoredUsersViewEvents.Failure -> showFailure(it.throwable)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt
index 9d58535490..1497c793c2 100644
--- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -50,7 +49,7 @@ class LegalsViewModel @AssistedInject constructor(
override fun handle(action: LegalsAction) {
when (action) {
LegalsAction.Refresh -> loadData()
- }.exhaustive
+ }
}
private fun loadData() = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt
index 4e1c62a4ec..cffef0da7b 100644
--- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt
@@ -17,12 +17,16 @@
package im.vector.app.features.settings.locale
import com.airbnb.epoxy.TypedEpoxyController
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
+import im.vector.app.core.epoxy.errorWithRetryItem
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.epoxy.noResultItem
import im.vector.app.core.epoxy.profiles.profileSectionItem
+import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.safeCapitalize
import im.vector.app.features.settings.VectorLocale
@@ -32,7 +36,8 @@ import javax.inject.Inject
class LocalePickerController @Inject constructor(
private val vectorPreferences: VectorPreferences,
- private val stringProvider: StringProvider
+ private val stringProvider: StringProvider,
+ private val errorFormatter: ErrorFormatter
) : TypedEpoxyController() {
var listener: Listener? = null
@@ -58,13 +63,14 @@ class LocalePickerController @Inject constructor(
title(host.stringProvider.getString(R.string.choose_locale_other_locales_title))
}
when (list) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("loading")
loadingText(host.stringProvider.getString(R.string.choose_locale_loading_locales))
}
}
- is Success ->
+ is Success ->
if (list().isEmpty()) {
noResultItem {
id("noResult")
@@ -84,6 +90,11 @@ class LocalePickerController @Inject constructor(
}
}
}
+ is Fail ->
+ errorWithRetryItem {
+ id("error")
+ text(host.errorFormatter.toHumanReadable(list.error))
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt
index 601574c908..d46b66dd87 100644
--- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerFragment.kt
@@ -26,7 +26,6 @@ import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.restart
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentLocalePickerBinding
@@ -54,7 +53,7 @@ class LocalePickerFragment @Inject constructor(
LocalePickerViewEvents.RestartActivity -> {
activity?.restart()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt
index d6b35fa4fe..0bbbc323e0 100644
--- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt
@@ -23,7 +23,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.configuration.VectorConfiguration
import im.vector.app.features.settings.VectorLocale
@@ -56,7 +55,7 @@ class LocalePickerViewModel @AssistedInject constructor(
override fun handle(action: LocalePickerAction) {
when (action) {
is LocalePickerAction.SelectLocale -> handleSelectLocale(action)
- }.exhaustive
+ }
}
private fun handleSelectLocale(action: LocalePickerAction.SelectLocale) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt
index 65c62542bb..73a74b1e3f 100644
--- a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt
@@ -28,7 +28,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentGenericRecyclerBinding
import org.matrix.android.sdk.api.session.pushers.Pusher
@@ -78,7 +77,7 @@ class PushGatewaysFragment @Inject constructor(
.setPositiveButton(android.R.string.ok, null)
.show()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt
index 1256673364..4d95447f2d 100644
--- a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-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
@@ -65,7 +64,7 @@ class PushGatewaysViewModel @AssistedInject constructor(@Assisted initialState:
when (action) {
is PushGatewayAction.Refresh -> handleRefresh()
is PushGatewayAction.RemovePusher -> removePusher(action.pusher)
- }.exhaustive
+ }
}
private fun removePusher(pusher: Pusher) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt
index d374357396..61d93b6f5f 100644
--- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsController.kt
@@ -21,11 +21,11 @@ import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.epoxy.noResultItem
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.getFormattedValue
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
@@ -78,6 +78,7 @@ class ThreePidsSettingsController @Inject constructor(
}
when (data.threePids) {
+ Uninitialized,
is Loading -> {
loadingItem {
id("loading")
@@ -160,7 +161,7 @@ class ThreePidsSettingsController @Inject constructor(
}
}
is ThreePidsSettingsUiState.AddingPhoneNumber -> Unit
- }.exhaustive
+ }
settingsSectionTitleItem {
id("msisdn")
@@ -223,7 +224,7 @@ class ThreePidsSettingsController @Inject constructor(
cancelOnClick { host.interactionListener?.cancelAdding() }
}
}
- }.exhaustive
+ }
}
private fun buildThreePid(idPrefix: String, threePid: ThreePid) {
diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt
index bdb1fb895f..ee7f8efab4 100644
--- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsFragment.kt
@@ -28,7 +28,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.getFormattedValue
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.isEmail
@@ -64,7 +63,7 @@ class ThreePidsSettingsFragment @Inject constructor(
when (it) {
is ThreePidsSettingsViewEvents.Failure -> displayErrorDialog(it.throwable)
is ThreePidsSettingsViewEvents.RequestReAuth -> askAuthentication(it)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt
index 12ff436ccb..acbe893d58 100644
--- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ReadOnceTrue
@@ -149,7 +148,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
uiaContinuation = null
pendingAuth = null
}
- }.exhaustive
+ }
}
var uiaContinuation: Continuation? = null
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
index 62fb064536..9dc433e96f 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
@@ -34,7 +34,6 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentIncomingShareBinding
@@ -81,7 +80,7 @@ class IncomingShareFragment @Inject constructor(
is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it)
is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it)
is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it)
- }.exhaustive
+ }
}
val intent = vectorBaseActivity.intent
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
index 4a413ad8ba..ca4148ebb7 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
@@ -22,7 +22,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.toggle
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.attachments.isPreviewable
@@ -96,7 +95,7 @@ class IncomingShareViewModel @AssistedInject constructor(
is IncomingShareAction.ShareMedia -> handleShareMediaToSelectedRooms(action)
is IncomingShareAction.FilterWith -> handleFilter(action)
is IncomingShareAction.UpdateSharedData -> handleUpdateSharedData(action)
- }.exhaustive
+ }
}
private fun handleUpdateSharedData(action: IncomingShareAction.UpdateSharedData) {
@@ -127,7 +126,7 @@ class IncomingShareViewModel @AssistedInject constructor(
is SharedData.Attachments -> {
shareAttachments(sharedData.attachmentData, state.selectedRoomIds, proposeMediaEdition = true, compressMediaBeforeSending = false)
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt
index 0cd9cde547..e2f3c14e7d 100644
--- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt
+++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutController.kt
@@ -18,8 +18,9 @@ package im.vector.app.features.signout.soft
import com.airbnb.epoxy.EpoxyController
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.error.ErrorFormatter
@@ -89,19 +90,20 @@ class SoftLogoutController @Inject constructor(
private fun buildForm(state: SoftLogoutViewState) {
val host = this
when (state.asyncHomeServerLoginFlowRequest) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("loading")
}
}
- is Fail -> {
+ is Fail -> {
loginErrorWithRetryItem {
id("errorRetry")
text(host.errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error))
listener { host.listener?.retry() }
}
}
- is Success -> {
+ is Success -> {
when (state.asyncHomeServerLoginFlowRequest.invoke()) {
LoginMode.Password -> {
loginPasswordFormItem {
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
index dff98722eb..1fc131ca86 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt
@@ -22,13 +22,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.epoxy.EpoxyTouchHelper
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.StateView
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentGroupListBinding
@@ -109,7 +109,7 @@ class SpaceListFragment @Inject constructor(
is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace)
is SpaceListViewEvents.OpenGroup -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup(it.groupingMethodHasChanged))
is SpaceListViewEvents.OpenSpaceInvite -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpaceInvite(it.id))
- }.exhaustive
+ }
}
}
@@ -121,8 +121,10 @@ class SpaceListFragment @Inject constructor(
override fun invalidate() = withState(viewModel) { state ->
when (state.asyncSpaces) {
- is Incomplete -> views.stateView.state = StateView.State.Loading
- is Success -> views.stateView.state = StateView.State.Content
+ Uninitialized,
+ is Loading -> views.stateView.state = StateView.State.Loading
+ is Success -> views.stateView.state = StateView.State.Content
+ else -> Unit
}
spaceController.update(state)
}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt
index 8ddeab3223..2b8276a4d7 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt
@@ -29,7 +29,6 @@ import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.isEmail
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@@ -192,7 +191,7 @@ class CreateSpaceViewModel @AssistedInject constructor(
is CreateSpaceAction.SetSpaceTopology -> {
handleSetTopology(action)
}
- }.exhaustive
+ }
}
private fun handleSetTopology(action: CreateSpaceAction.SetSpaceTopology) {
diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt
index 85f80960b0..12ae8fc1f9 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt
@@ -85,6 +85,7 @@ class SpaceManageActivity : VectorBaseActivity() {
when (sharedAction) {
is RoomDirectorySharedAction.Back,
is RoomDirectorySharedAction.Close -> finish()
+ else -> Unit
}
}
.launchIn(lifecycleScope)
diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt
index bedd1873e8..2a2598075f 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt
@@ -22,7 +22,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.session.Session
@@ -51,6 +50,6 @@ class SpaceManageSharedViewModel @AssistedInject constructor(
SpaceManagedSharedAction.ManageRooms -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToManageRooms)
SpaceManagedSharedAction.OpenSpaceAliasesSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToAliasSettings)
SpaceManagedSharedAction.OpenSpacePermissionSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToPermissionSettings)
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt
index 266d08fd12..db9420abc2 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt
@@ -34,7 +34,6 @@ import im.vector.app.R
import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
@@ -102,7 +101,7 @@ class SpaceSettingsFragment @Inject constructor(
ignoreChanges = true
vectorBaseActivity.onBackPressed()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleViewModel.kt
index 55d1dbe61e..2e386697d4 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleViewModel.kt
@@ -25,7 +25,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.raw.wellknown.isE2EByDefault
@@ -52,7 +51,7 @@ class SpacePeopleViewModel @AssistedInject constructor(
when (action) {
is SpacePeopleViewAction.ChatWith -> handleChatWith(action)
SpacePeopleViewAction.InviteToSpace -> handleInviteToSpace()
- }.exhaustive
+ }
}
private fun handleInviteToSpace() {
diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsActivity.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsActivity.kt
index e6071fdd2a..9a86e550a8 100644
--- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsActivity.kt
@@ -23,7 +23,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.SimpleFragmentActivity
import org.matrix.android.sdk.api.session.terms.TermsService
@@ -63,7 +62,7 @@ class ReviewTermsActivity : SimpleFragmentActivity() {
setResult(Activity.RESULT_OK)
finish()
}
- }.exhaustive
+ }
}
}
diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt
index cb76e5b31f..53afbf7a07 100644
--- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt
@@ -29,7 +29,6 @@ import im.vector.app.R
import im.vector.app.core.epoxy.onClick
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.openUrlInChromeCustomTab
import im.vector.app.databinding.FragmentReviewTermsBinding
@@ -70,7 +69,7 @@ class ReviewTermsFragment @Inject constructor(
ReviewTermsViewEvents.Success -> {
// Handled by the Activity
}
- }.exhaustive
+ }
}
reviewTermsViewModel.handle(ReviewTermsAction.LoadTerms(getString(R.string.resources_language)))
diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt
index 9932efb11a..8fe1f598f6 100644
--- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsViewModel.kt
@@ -24,7 +24,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-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
@@ -49,7 +48,7 @@ class ReviewTermsViewModel @AssistedInject constructor(
is ReviewTermsAction.LoadTerms -> loadTerms(action)
is ReviewTermsAction.MarkTermAsAccepted -> markTermAsAccepted(action)
ReviewTermsAction.Accept -> acceptTerms()
- }.exhaustive
+ }
}
private fun markTermAsAccepted(action: ReviewTermsAction.MarkTermAsAccepted) = withState { state ->
diff --git a/vector/src/main/java/im/vector/app/features/terms/TermsController.kt b/vector/src/main/java/im/vector/app/features/terms/TermsController.kt
index 6109e9abc8..10238829b3 100644
--- a/vector/src/main/java/im/vector/app/features/terms/TermsController.kt
+++ b/vector/src/main/java/im/vector/app/features/terms/TermsController.kt
@@ -17,8 +17,9 @@ package im.vector.app.features.terms
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
+import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.Uninitialized
import im.vector.app.R
import im.vector.app.core.epoxy.errorWithRetryItem
import im.vector.app.core.epoxy.loadingItem
@@ -38,19 +39,20 @@ class TermsController @Inject constructor(
val host = this
when (data.termsList) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
loadingItem {
id("loading")
}
}
- is Fail -> {
+ is Fail -> {
errorWithRetryItem {
id("errorRetry")
text(host.errorFormatter.toHumanReadable(data.termsList.error))
listener { host.listener?.retry() }
}
}
- is Success -> buildTerms(data.termsList.invoke())
+ is Success -> buildTerms(data.termsList.invoke())
}
}
@@ -67,7 +69,7 @@ class TermsController @Inject constructor(
description(host.description)
checked(term.accepted)
- clickListener { host.listener?.review(term) }
+ clickListener { host.listener?.review(term) }
checkChangeListener { _, isChecked ->
host.listener?.setChecked(term, isChecked)
}
diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt
index 356893aee2..9e0aa15297 100644
--- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeActivity.kt
@@ -30,7 +30,6 @@ import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.onPermissionDeniedSnackbar
@@ -127,7 +126,7 @@ class UserCodeActivity : VectorBaseActivity(),
Toast.makeText(this, R.string.qr_code_not_scanned, Toast.LENGTH_SHORT).show()
finish()
}
- }.exhaustive
+ }
}
}
@@ -153,7 +152,7 @@ class UserCodeActivity : VectorBaseActivity(),
UserCodeState.Mode.SHOW -> super.onBackPressed()
is UserCodeState.Mode.RESULT,
UserCodeState.Mode.SCAN -> sharedViewModel.handle(UserCodeActions.SwitchMode(UserCodeState.Mode.SHOW))
- }.exhaustive
+ }
}
companion object {
diff --git a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt
index 64bcf9cead..da894a42be 100644
--- a/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/usercode/UserCodeSharedViewModel.kt
@@ -62,12 +62,12 @@ class UserCodeSharedViewModel @AssistedInject constructor(
override fun handle(action: UserCodeActions) {
when (action) {
- UserCodeActions.DismissAction -> _viewEvents.post(UserCodeShareViewEvents.Dismiss)
- is UserCodeActions.SwitchMode -> setState { copy(mode = action.mode) }
- is UserCodeActions.DecodedQRCode -> handleQrCodeDecoded(action)
- is UserCodeActions.StartChattingWithUser -> handleStartChatting(action)
+ UserCodeActions.DismissAction -> _viewEvents.post(UserCodeShareViewEvents.Dismiss)
+ is UserCodeActions.SwitchMode -> setState { copy(mode = action.mode) }
+ is UserCodeActions.DecodedQRCode -> handleQrCodeDecoded(action)
+ is UserCodeActions.StartChattingWithUser -> handleStartChatting(action)
is UserCodeActions.CameraPermissionNotGranted -> _viewEvents.post(UserCodeShareViewEvents.CameraPermissionNotGranted(action.deniedPermanently))
- UserCodeActions.ShareByText -> handleShareByText()
+ UserCodeActions.ShareByText -> handleShareByText()
}
}
@@ -110,11 +110,11 @@ class UserCodeSharedViewModel @AssistedInject constructor(
_viewEvents.post(UserCodeShareViewEvents.ShowWaitingScreen)
viewModelScope.launch(Dispatchers.IO) {
when (linkedId) {
- is PermalinkData.RoomLink -> {
+ is PermalinkData.RoomLink -> {
// not yet supported
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
}
- is PermalinkData.UserLink -> {
+ is PermalinkData.UserLink -> {
val user = tryOrNull { session.resolveUser(linkedId.userId) }
// Create raw Uxid in case the user is not searchable
?: User(linkedId.userId, null, null)
@@ -125,14 +125,15 @@ class UserCodeSharedViewModel @AssistedInject constructor(
)
}
}
- is PermalinkData.GroupLink -> {
+ is PermalinkData.GroupLink -> {
// not yet supported
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
}
- is PermalinkData.FallbackLink -> {
+ is PermalinkData.FallbackLink -> {
// not yet supported
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
}
+ is PermalinkData.RoomEmailInviteLink -> Unit
}
_viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen)
}
diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt
index 61f8bc35f3..039c7041b0 100644
--- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt
@@ -26,7 +26,6 @@ import dagger.assisted.AssistedInject
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.isEmail
import im.vector.app.core.extensions.toggle
import im.vector.app.core.platform.VectorViewModel
@@ -113,7 +112,7 @@ class UserListViewModel @AssistedInject constructor(
UserListAction.UserConsentRequest -> handleUserConsentRequest()
is UserListAction.UpdateUserConsent -> handleISUpdateConsent(action)
UserListAction.Resumed -> handleResumed()
- }.exhaustive
+ }
}
private fun handleUserConsentRequest() {
diff --git a/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt b/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt
new file mode 100644
index 0000000000..32f30fe458
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/voice/AudioWaveformView.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.voice
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+import im.vector.app.R
+import kotlin.math.max
+import kotlin.random.Random
+
+class AudioWaveformView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
+
+ private enum class Alignment(var value: Int) {
+ CENTER(0),
+ BOTTOM(1),
+ TOP(2)
+ }
+
+ private enum class Flow(var value: Int) {
+ LTR(0),
+ RTL(1)
+ }
+
+ data class FFT(val value: Float, var color: Int)
+
+ private fun Int.dp() = this * Resources.getSystem().displayMetrics.density
+
+ // Configuration fields
+ private var alignment = Alignment.CENTER
+ private var flow = Flow.LTR
+ private var verticalPadding = 4.dp()
+ private var horizontalPadding = 4.dp()
+ private var barWidth = 2.dp()
+ private var barSpace = 1.dp()
+ private var barMinHeight = 1.dp()
+ private var isBarRounded = true
+
+ private val rawFftList = mutableListOf()
+ private var visibleBarHeights = mutableListOf()
+
+ private val barPaint = Paint()
+
+ init {
+ attrs?.let {
+ context
+ .theme
+ .obtainStyledAttributes(
+ attrs,
+ R.styleable.AudioWaveformView,
+ 0,
+ 0
+ )
+ .apply {
+ alignment = Alignment.values().find { it.value == getInt(R.styleable.AudioWaveformView_alignment, alignment.value) }!!
+ flow = Flow.values().find { it.value == getInt(R.styleable.AudioWaveformView_flow, alignment.value) }!!
+ verticalPadding = getDimension(R.styleable.AudioWaveformView_verticalPadding, verticalPadding)
+ horizontalPadding = getDimension(R.styleable.AudioWaveformView_horizontalPadding, horizontalPadding)
+ barWidth = getDimension(R.styleable.AudioWaveformView_barWidth, barWidth)
+ barSpace = getDimension(R.styleable.AudioWaveformView_barSpace, barSpace)
+ barMinHeight = getDimension(R.styleable.AudioWaveformView_barMinHeight, barMinHeight)
+ isBarRounded = getBoolean(R.styleable.AudioWaveformView_isBarRounded, isBarRounded)
+ setWillNotDraw(false)
+ barPaint.isAntiAlias = true
+ }
+ .apply { recycle() }
+ .also {
+ barPaint.strokeWidth = barWidth
+ barPaint.strokeCap = if (isBarRounded) Paint.Cap.ROUND else Paint.Cap.BUTT
+ }
+ }
+ }
+
+ fun initialize(fftList: List) {
+ handleNewFftList(fftList)
+ invalidate()
+ }
+
+ fun add(fft: FFT) {
+ handleNewFftList(listOf(fft))
+ invalidate()
+ }
+
+ fun summarize() {
+ if (rawFftList.isEmpty()) return
+
+ val maxVisibleBarCount = getMaxVisibleBarCount()
+ val summarizedFftList = rawFftList.summarize(maxVisibleBarCount)
+ clear()
+ handleNewFftList(summarizedFftList)
+ invalidate()
+ }
+
+ fun updateColors(limitPercentage: Float, colorBefore: Int, colorAfter: Int) {
+ val size = visibleBarHeights.size
+ val limitIndex = (size * limitPercentage).toInt()
+ visibleBarHeights.forEachIndexed { index, fft ->
+ fft.color = if (index < limitIndex) {
+ colorBefore
+ } else {
+ colorAfter
+ }
+ }
+ invalidate()
+ }
+
+ fun clear() {
+ rawFftList.clear()
+ visibleBarHeights.clear()
+ }
+
+ private fun List.summarize(target: Int): List {
+ flow = Flow.LTR
+ val result = mutableListOf()
+ if (size <= target) {
+ result.addAll(this)
+ val missingItemCount = target - size
+ repeat(missingItemCount) {
+ val index = Random.nextInt(result.size)
+ result.add(index, result[index])
+ }
+ } else {
+ val step = (size.toDouble() - 1) / (target - 1)
+ var index = 0.0
+ while (index < size) {
+ result.add(get(index.toInt()))
+ index += step
+ }
+ }
+ return result
+ }
+
+ private fun handleNewFftList(fftList: List) {
+ val maxVisibleBarCount = getMaxVisibleBarCount()
+ fftList.forEach { fft ->
+ rawFftList.add(fft)
+ val barHeight = max(fft.value / MAX_FFT * (height - verticalPadding * 2), barMinHeight)
+ visibleBarHeights.add(FFT(barHeight, fft.color))
+ if (visibleBarHeights.size > maxVisibleBarCount) {
+ visibleBarHeights = visibleBarHeights.subList(visibleBarHeights.size - maxVisibleBarCount, visibleBarHeights.size)
+ }
+ }
+ }
+
+ private fun getMaxVisibleBarCount() = ((width - horizontalPadding * 2) / (barWidth + barSpace)).toInt()
+
+ private fun drawBars(canvas: Canvas) {
+ var currentX = horizontalPadding
+ val flowableBarHeights = if (flow == Flow.LTR) visibleBarHeights else visibleBarHeights.reversed()
+
+ flowableBarHeights.forEach {
+ barPaint.color = it.color
+ when (alignment) {
+ Alignment.BOTTOM -> {
+ val startY = height - verticalPadding
+ val stopY = startY - it.value
+ canvas.drawLine(currentX, startY, currentX, stopY, barPaint)
+ }
+ Alignment.CENTER -> {
+ val startY = (height - it.value) / 2
+ val stopY = startY + it.value
+ canvas.drawLine(currentX, startY, currentX, stopY, barPaint)
+ }
+ Alignment.TOP -> {
+ val startY = verticalPadding
+ val stopY = startY + it.value
+ canvas.drawLine(currentX, startY, currentX, stopY, barPaint)
+ }
+ }
+ currentX += barWidth + barSpace
+ }
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ drawBars(canvas)
+ }
+
+ companion object {
+ const val MAX_FFT = 32760
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt
index 963bd9521c..77ec4c5b06 100644
--- a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt
@@ -80,6 +80,7 @@ class WidgetActivity : VectorBaseActivity() {
viewModel.observeViewEvents {
when (it) {
is WidgetViewEvents.Close -> handleClose(it)
+ else -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt
index 8fa9e07848..dbd63186b6 100644
--- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt
@@ -29,7 +29,6 @@ import android.view.ViewGroup
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Incomplete
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
@@ -87,6 +86,7 @@ class WidgetFragment @Inject constructor() :
is WidgetViewEvents.OnURLFormatted -> loadFormattedUrl(it)
is WidgetViewEvents.DisplayIntegrationManager -> displayIntegrationManager(it)
is WidgetViewEvents.Failure -> displayErrorDialog(it.throwable)
+ is WidgetViewEvents.Close -> Unit
}
}
viewModel.handle(WidgetAction.LoadFormattedUrl)
@@ -192,13 +192,14 @@ class WidgetFragment @Inject constructor() :
override fun invalidate() = withState(viewModel) { state ->
Timber.v("Invalidate state: $state")
when (state.formattedURL) {
- is Incomplete -> {
+ Uninitialized,
+ is Loading -> {
setStateError(null)
views.widgetWebView.isInvisible = true
views.widgetProgressBar.isIndeterminate = true
views.widgetProgressBar.isVisible = true
}
- is Success -> {
+ is Success -> {
setStateError(null)
when (state.webviewLoadedUrl) {
Uninitialized -> {
@@ -221,7 +222,7 @@ class WidgetFragment @Inject constructor() :
}
}
}
- is Fail -> {
+ is Fail -> {
// we need to show Error
views.widgetWebView.isInvisible = true
views.widgetProgressBar.isVisible = false
diff --git a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt
index f29e6d1928..78871da324 100644
--- a/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/widgets/permissions/RoomWidgetPermissionViewModel.kt
@@ -93,6 +93,7 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
when (action) {
RoomWidgetPermissionActions.AllowWidget -> handleAllowWidget()
RoomWidgetPermissionActions.BlockWidget -> handleRevokeWidget()
+ RoomWidgetPermissionActions.DoClose -> Unit
}
}
diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt
index 4daaef6fe1..fbc0b8fcff 100644
--- a/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/workers/signout/SignoutCheckViewModel.kt
@@ -28,7 +28,6 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
-import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
@@ -124,7 +123,7 @@ class SignoutCheckViewModel @AssistedInject constructor(
copy(hasBeenExportedToFile = Success(true))
}
}
- }.exhaustive
+ }
}
private fun handleExportKeys(action: Actions.ExportKeys) {
diff --git a/vector/src/main/res/drawable/ic_presence_online.xml b/vector/src/main/res/drawable/ic_presence_online.xml
index 2184f359b2..e5229de3fd 100644
--- a/vector/src/main/res/drawable/ic_presence_online.xml
+++ b/vector/src/main/res/drawable/ic_presence_online.xml
@@ -16,7 +16,7 @@
diff --git a/vector/src/main/res/layout/fragment_timeline.xml b/vector/src/main/res/layout/fragment_timeline.xml
index 6ba326bcc4..14eac04db2 100644
--- a/vector/src/main/res/layout/fragment_timeline.xml
+++ b/vector/src/main/res/layout/fragment_timeline.xml
@@ -17,7 +17,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
- android:visibility="gone"/>
+ android:visibility="gone" />
+
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/locationLiveStatusIndicator" />
+ app:layout_constraintTop_toBottomOf="@id/removeJitsiWidgetView" />
+ app:layout_constraintBottom_toTopOf="@id/composerLayout"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/timelineRecyclerView"
+ tools:visibility="visible" />
+ tools:visibility="visible" />
+ app:layout_constraintStart_toStartOf="parent" />
-
+
+
+
+
+
+
+
+
+
+
diff --git a/vector/src/main/res/layout/view_room_detail_toolbar.xml b/vector/src/main/res/layout/view_room_detail_toolbar.xml
index befd84ea34..d5c1914d41 100644
--- a/vector/src/main/res/layout/view_room_detail_toolbar.xml
+++ b/vector/src/main/res/layout/view_room_detail_toolbar.xml
@@ -19,15 +19,6 @@
app:layout_constraintTop_toTopOf="parent"
tools:src="@sample/room_round_avatars" />
-
-
@@ -59,27 +48,50 @@
tools:ignore="MissingConstraints"
tools:visibility="invisible" />
+
+
+ app:constraint_referenced_ids="roomToolbarAvatarImageView,roomToolbarAvatarShield,roomToolbarPresenceImageView,roomToolbarPublicImageView" />
+
+
- فشلت إزالة الودجةفشلت إضافة الودجةيستمع للإشعارات
+ ينتظر…
+ تفاعلَ بـ: %s
+ استبيان
+ ملصق
+ ملف
+ تسجيل صوتي
+ صوت
+ صورة.
+ فيديو.
+ ليس آمن
+ ينشئ فضاءً…
+ فشل إرسال الاقتراح (%s)
+ شكرًا، أُرسل اقتراحك
+ صِف اقتراحك
+ اكتب اقتراحك أدناه.
+ إعدادات النظام
+ احصل على المساعدة باستخدام ${app_name}
+ الصوت والفيديو
+ الأمان والخصوصية
+ الخيارات
+ عام
+ "أُنشئت الغرفة، لكن فشل إرسال بعض الدعوات بسبب:
+\n
+\n%s"
+ يمكن لأي شخص الإنضمام لهذه الغرفة
+ علنية
+ إعدادات الغرفة
+ الموضوع
+ موضوع الغرفة (اختياري)
+ الاسم
+ اسم الغرفة
+ أنشئ
+ رسالة مباشرة
+ الغرف
+ لا يمكنك معاينة هذه الغرفة، هل تريد الإنضمام إليها؟
+ لا يمكنك الوصول إلى هذه الغرفة حاليًا.
+\nحاول لاحقًا، أو اسأل مدير الغرفة إن كان لديك نفاذ لها.
+ تتعذر معاية هذه الغرفة
+ كل المجتمعات
+ رجاء انتظر…
+ غيّر الشبكة
+ أنشئ فضاء جديد
+ أنشئ غرفة جديدة
+ حدث حذفه مستخدم
+ اعرض الرسائل المحذوفة
+ حُذفت الرسالة
+ الانفعالات
+ اعرض الانفعالات
+ أضف انفعالًا
+ الانفعالات
\ No newline at end of file
diff --git a/vector/src/main/res/values-cs/strings.xml b/vector/src/main/res/values-cs/strings.xml
index cf022172c2..c7e0f96433 100644
--- a/vector/src/main/res/values-cs/strings.xml
+++ b/vector/src/main/res/values-cs/strings.xml
@@ -932,7 +932,7 @@
OpakovatPoslali Vám pozvánku%s Vás pozval
- Vše jste dohnali!
+ To je všechno!Nemáte již žádné nepřečtené zprávyKonverzaceTady budou zobrazeny Vaše přímé konverzace. Pro novou zprávu klepněte na + vpravo dole.
diff --git a/vector/src/main/res/values-de/strings.xml b/vector/src/main/res/values-de/strings.xml
index 7a8ac9c71b..4c5131d452 100644
--- a/vector/src/main/res/values-de/strings.xml
+++ b/vector/src/main/res/values-de/strings.xml
@@ -1079,7 +1079,7 @@
Erweitere und individualisiere dein BenutzererlebnisMit %1$s verbindenMit Element Matrix Services verbinden
- Mit einem individuellen Server verbinden
+ Mit einem anderen Server verbindenBei %1$s anmeldenRegistrierenAnmelden
@@ -1257,7 +1257,7 @@
Raum verlassenVerlasse den Raum…Administratoren
- Moderationen
+ ModeratorenBenutzerdefiniertEingeladenNutzer
@@ -2380,7 +2380,7 @@
Organisiere Diskussionen mit ThreadsThreads im Raum filternMöchtest du einem existierenden Server beitreten\?
- Communities
+ GemeinschaftenTeamsWir helfen dir, in Verbindung zu kommen.Mit wem wirst du am meisten chatten\?
diff --git a/vector/src/main/res/values-el/strings.xml b/vector/src/main/res/values-el/strings.xml
index fb4956444a..a7da13bdb3 100644
--- a/vector/src/main/res/values-el/strings.xml
+++ b/vector/src/main/res/values-el/strings.xml
@@ -1,7 +1,6 @@
Ηλεκτρονική διεύθυνση
-
Ο/Η %1$s σας προσκάλεσεΟ/Η %1$s αποχώρησεΟ/Η %1$s απέρριψε την πρόσκληση
@@ -9,7 +8,6 @@
Ο/Η %1$s προσκάλεσε τον/την %2$sΗ πρόσκληση του/της %sΑριθμός τηλεφώνου
-
Ο/Η %1$s απέκλεισε τον/την %2$sΟ/Η %1$s απέσυρε την πρόσκληση του/της %2$sΟ/Η %1$s άλλαξε εικονίδιο χρήστη
@@ -20,7 +18,6 @@
Ο/Η %1$s άλλαξε το όνομα του δωματίου σε: %2$sΟ/Η %s απάντησε στην κλήση.Ο/Η %s τερμάτισε την κλήση.
-
Ο/Η %s πραγματοποίησε μια κλήση βίντεο.Ο/Η %s πραγματοποίησε μια κλήση ήχου.Ο/Η %1$s κατέστησε το μελλοντικό ιστορικό του δωματίου ορατό στον/στην %2$s
@@ -31,28 +28,15 @@
Ο/Η %1$s αφαίρεσε το όνομα του δωματίουΟ/Η %1$s αφαίρεσε το θέμα του δωματίουΟ/Η %1$s δέχτηκε την πρόσκληση για το %2$s
-
** Αδυναμία αποκρυπτογράφησης: %s **Η συσκευή του/της αποστολέα δεν μας έχει στείλει τα κλειδιά για αυτό το μήνυμα.
-
Αποτυχία αποστολής μηνύματος
-
-
Σφάλμα του Matrix
-
-
Ο/Η %1$s εισήλθε στο δωμάτιο
-
Πρόσκληση στο δωμάτιο
-
%1$s και %2$s
-
-
-
Άδειο δωμάτιο
-
όλα τα μέλη του δωματίου από την στιγμή που εισήλθαν.
-
Ο/Η %1$s έστειλε μία πρόσκληση στον/στην %2$s για να εισέλθει στο δωμάτιοΑκύρωσηΚλείσιμο
@@ -108,7 +92,6 @@
Μόνο οι επαφές MatrixΔεν βρέθηκαν αποτελέσματαΔωμάτια
-
ΚοινότητεςΑποστολή καταγραφών σφαλμάτωνΑναφορά σφάλματος
@@ -214,8 +197,6 @@
Σφάλμα εντολήςΔημιουργίαΔωμάτια
-
-
Λόγος: %1$sΑπενεργοποίηση λογαριασμούΑπενεργοποίηση λογαριασμού
@@ -295,7 +276,6 @@
%d πρόσκληση%d προσκλήσεις
-
ΣύνδεσηΛόγος οριστικής αποβολήςΑποκλεισμός χρήστη
@@ -353,7 +333,6 @@
Αποτυχία σύνδεσης σε πραγματικό χρόνο.
\nΖητήστε από τον διαχειριστή του οικιακού σας διακομιστή να διαμορφώσει έναν διακομιστή TURN ώστε οι κλήσεις να λειτουργούν αξιόπιστα.Η Κλήση ${app_name} Aπέτυχε
-
Είσαστε σίγουροι ότι θέλετε να κάνετε κλήση βίντεο;Είσαστε σίγουροι ότι θέλετε να κάνετε κλήση ήχου;Αποστολή φωνής
@@ -369,7 +348,6 @@
Κατάργηση δημοσίευσηςΑντιγραφήΤέλος κλήσης
-
ΕιδοποιήσειςΑντιγράφηκε στο πρόχειροΠρόσθεση
@@ -392,7 +370,6 @@
%s γράφει…%1$s & %2$s γράφουν…Δεν εξακριβώθηκε η ταυτότητα του εξωτερικού διακομιστή.
-
Κανένα αποτέλεσμαΦιλτράρισμα αποβεβλημένων χρηστώνΦιλτράρισμα μελών δωματίου
@@ -402,4 +379,9 @@
Το πιστοποιητικό έχει αλλάξει από αυτό που εμπιστεύθηκε προηγουμένως η συσκευή σας. Αυτό είναι ΑΚΡΩΣ ΑΣΥΝΗΘΙΣΤΟ. Προτείνεται να ΜΗΝ ΑΠΟΔΕΚΤΕΙΤΕ το νεο πιστοποιητικό.Προεπιλογή ΣυστήματοςΛανθασμένο όνομα χρήστη και/ή κωδικού
+ Τερματισμός δημοσκόπησης
+ Επεξεργασία δημοσκόπησης
+ Άνοιγμα με
+ Αποστολή αυτοκόλλητου
+ %1$s δημιούργησε το δωμάτιο
\ No newline at end of file
diff --git a/vector/src/main/res/values-es/strings.xml b/vector/src/main/res/values-es/strings.xml
index 8e0568e7ae..0f80bc8e0f 100644
--- a/vector/src/main/res/values-es/strings.xml
+++ b/vector/src/main/res/values-es/strings.xml
@@ -39,7 +39,6 @@
Invitación a Sala%1$s y %2$sSala vacía
-
%1$s ha revocado la invitación a unirse a la sala para %2$sSincronización inicial
\nImportando cuenta…
@@ -241,7 +240,6 @@
EliminarRenombrarReportar contenido
-
oInvitarCerrar sesión
@@ -264,7 +262,6 @@
Solo contactos de MatrixNo hay resultadosSalas
-
Enviar registrosEnviar registros de fallasEnviar captura de pantalla
@@ -292,11 +289,9 @@
Esto no parece ser una dirección de correo electrónico válidaEsta dirección de correo electrónico ya está definida.¿Olvidaste tu contraseña?
-
Este Servidor Doméstico quiere asegurarse de que no eres un robotDebes ingresar la dirección de correo electrónico vinculada a tu cuenta.No se pudo verificar la dirección de correo electrónico: asegúrate de hacer clic en el enlace del correo electrónico
-
Por favor introduce una URL válidaJSON mal formadoNo contenía un JSON válido
@@ -312,15 +307,10 @@
Llamada En Curso…El lado remoto no contestó.Información
-
-
${app_name} necesita permiso para acceder a tu micrófono para realizar llamadas de voz.
-
${app_name} necesita permiso para acceder a tu cámara y micrófono para realizar llamadas de vídeo.
\n
\nPor favor permite el acceso en las próximas ventanas emergentes para poder realizar la llamada.
-
-
SÍNOContinuar
@@ -328,7 +318,6 @@
UnirseRechazarMensajes no leídos.
-
Salir de la sala¿Seguro que quieres salir de la sala?CONVERSACIONES DIRECTAS
@@ -355,7 +344,6 @@
El certificado cambió de uno que era confiable para tu teléfono. Esto es MUY INUSUAL. Se recomienda NO ACEPTAR este nuevo certificado.El certificado cambió de uno que era confiable a uno que no es confiable. El servidor puede haber renovado su certificado. Contacta al administrador del servidor para obtener la huella digital.Solo acepta el certificado si el administrador del servidor ha publicado una huella digital que coincide con la anterior.
-
BuscarFiltrar miembros de la salaNo hay resultados
@@ -400,7 +388,6 @@
Actualizar Nombre PúblicoVisto por última vez%1$s @ %2$s
-
AutenticaciónSesión iniciada comoServidor Doméstico
@@ -431,7 +418,6 @@
Estas son funcionalidades experimentales que pueden romperse de maneras inesperadas. Utilizar con precaución.Establecer como dirección principalDejar de Establecer como dirección principal
-
Error de descifradoNombre públicoID de sesión
@@ -442,7 +428,6 @@
ExportarIngresar frase de contraseñaConfirmar frase de contraseña
-
Importar claves de salas con cifrado Extremo-a-ExtremoImportar claves de salaImportar las claves desde un archivo local
@@ -454,7 +439,6 @@
VerificarPara verificar que esta sesión es confiable, por favor contacta a su dueño por algún otro medio (ej. cara a cara o por teléfono) y pregúntale si la clave que ve en sus Ajustes de Usuario para esta sesión coincide con la clave a continuación:Si coincide, presione el botón de verificar a continuación. Si no coincide, entonces alguien está interceptando esta sesión y probablemente debería prohibirlo. En el futuro, este proceso de verificación será más sofisticado.
-
Selecciona un directorio de salasNombre del servidorTodas las salas en el servidor %s
@@ -540,8 +524,6 @@
%d mensaje nuevo%d mensajes nuevos
-
-
%d sala%d salas
@@ -550,12 +532,10 @@
%d cambio de membresía%d cambios de membresía
-
%d mensaje sin leer%d mensajes sin leer
-
%1$s en %2$s%d componente activo
@@ -608,16 +588,10 @@
Haz clic aquí para ver mensajes más antiguosDegrada al usuario con la ID dadaAlertas de Sistema
-
-
-
-
$d seleccionado%d seleccionados
-
-
contacta al administrador de tu servicioEste servidor doméstico ha excedido uno de sus límites de recursos, por lo que algunos usuarios no podrán iniciar sesión.Este servidor doméstico ha excedido uno de sus límites de recursos.
@@ -741,7 +715,6 @@
Incluye cambios en el avatar y en el nombre.Enviar mensaje con introLa tecla Intro enviará el mensaje en vez de añadir un salto de línea
-
ContraseñaLa contraseña no es válidaMedia
@@ -801,7 +774,6 @@
Guardar clave de recuperaciónCompartirGuardar como archivo
-
Por favor, haga una copiaCompartir clave de recuperación con…Generando clave de recuperación usando una contraseña, este proceso puede tardar varios segundos.
@@ -848,7 +820,6 @@
Cargando %d de las claves…Firma
-
Origen predeterminado de mediosConfigurar copia de seguridad de las claves de cifradoObteniendo una versión de copia de seguridad…
@@ -857,7 +828,6 @@
La copia de seguridad tiene una firma inválida de la sesión no verificada %sPara usar la copia de seguridad de la clave en esta sesión introduzca su contraseña o su clave de recuperación ahora.¿Deseas borrar tus claves de cifrado guardadas en el servidor\? No podrás usar tu clave de recuperación para leer el historial de mensajes cifrados.
-
Reproducir sonido de cámaraip desconocidaUna nueva sesión solicita claves de cifrado.
@@ -878,8 +848,6 @@
Comprobando copias de respaldo¡Verificado!Ok
-
-
Solicitud de verificación%s quiere verificar tu sesiónError desconocido
@@ -933,7 +901,6 @@
IntegracionesDescubrimientoGestione sus preferencias de descubrimiento.
-
Esta no es una dirección de servidor Matrix válidaNo se puede acceder al servidor en esta URL, por favor, compruébeloModo Sincronización en segundo plano
@@ -942,7 +909,6 @@
${app_name} se sincronizará en segundo plano periódicamente en un momento preciso (configurable).
\nEsto afectará al uso de la radio y la batería, se mostrará una notificación permanente que indica que ${app_name} está escuchando a nuevos acontecimientos.No se le notificará de los mensajes entrantes cuando la aplicación esté en segundo plano.
-
Utiliza un Gestor de Integración para gestionar los bots, puentes, widgets y paquetes de pegatinas.
\nLos Gestores de Integración reciben los datos de configuración y pueden modificar los widgets, enviar invitaciones a salas y establecer niveles de poder en su nombre.Permitir integraciones
@@ -1078,7 +1044,6 @@
Este contenido fue reportado como inapropiado.
\n
\nSi no quieres ver más contenido de este usuario, puedes bloquearlo para ocultar sus mensajes.
-
Ignorar usuarioTodos los mensajes (sonido)Todos los mensajes
@@ -1508,7 +1473,6 @@
\n- El servidor privado al que está conectado el usuario que estás verificando
\n- Su conexión a internet o la de otros usuarios
\n- Su dispositivo o el de otros usuarios
-
Los mensajes de esta sala están cifrados Extremo-a-Extremo.
\n
\nSus mensajes están protegidos y sólo usted y el destinatario tienen las claves únicas para descifrarlos.
@@ -1589,7 +1553,6 @@
Imprímelo y guárdalo en un lugar seguroGuárdelo en una llave USB o unidad de respaldoCópielo en su almacenamiento personal en la nube
-
Si cancela ahora, puede perder mensajes y datos cifrados si pierde el acceso a sus inicios de sesión.
\n
\nTambién puede configurar la Copia de Seguridad Segura y administrar sus claves en Configuración.
@@ -1937,7 +1900,6 @@
TransferirConectarPreguntar primero
-
Llamada activa (%1$s)Pad de marcadoEsta llamada ha terminado
@@ -2062,7 +2024,6 @@
Para llevar a cabo esta acción has de otorgar el permiso de Cámara en las preferencias del sistema.Se requieren permisos para llevar a cabo esta acción. Por favor, otórgalos desde las preferencias del sistema.Impedir a cualquiera que no forme parte de %s unirse a este sala
-
Dar consentimientoRevocar consentimientoHas dado tu consentimiento para enviar emails y números de teléfono a este servidor identidad para descubrir a otros usuarios desde tus contactos.
@@ -2087,7 +2048,6 @@
Actualización requeridaActualizarPor favor, se paciente. Ésto puede llevar algo de tiempo.
-
Sala sin nombrePor favor, contacta con el administrador de tu homeserver para más informaciónParece que tu homeserver no soporta Espacios todavía
@@ -2143,7 +2103,6 @@
Transferir a %1$sConsultando con %1$sOcurrió un error al transferir la llamada
-
Hubo un error al buscar el número de teléfonoDevolver la llamadaBuscar contactos en Matrix
@@ -2312,4 +2271,37 @@
Ver en la salaHabilitarNo estás autorizado a unirte a esta sala
+ ¿No lo sabes todavía\? Puedes %s
+ saltar esta pregunta
+ Comunidades
+ Equipos
+ Familia y amigos
+ Te vamos a ayudar a conectarte.
+ ¿Con quién hablarás más\?
+ Mensajería para tu equipo.
+ Mensajería segura.
+ Tú mandas.
+ Toma el control de tus conversaciones.
+ Ubicación
+ Encuesta
+ ¿Aceptas enviar esta información\?
+ Ajustes del sistema
+ Versiones
+ Obtén ayuda sobre cómo usar ${app_name}
+ Ayuda
+ Ayuda
+ Asuntos legales
+ ¡Ya estás viendo este hilo!
+ Ver en la sala
+ Responder en un hilo
+ El comando «%s» existe, pero no funciona dentro de hilos.
+ Este servidor no ha devuelto ninguna política.
+ Bibliotecas de terceros
+ Política de tu servidor de identidad
+ Política de tu servidor base
+ Política de ${app_name}
+ %1$s y %2$s
+ Filtrar
+ %1$s, %2$s y otros
+ Copiar enlace al hilo
\ No newline at end of file
diff --git a/vector/src/main/res/values-fa/strings.xml b/vector/src/main/res/values-fa/strings.xml
index eb8a29b6b2..a3ee61013e 100644
--- a/vector/src/main/res/values-fa/strings.xml
+++ b/vector/src/main/res/values-fa/strings.xml
@@ -40,7 +40,6 @@
شماره تلفندعوت اتاق%1$s و %2$s
-
اتاق خالیهمگامسازی نخستین:
\nدرونریزی حساب…
@@ -221,7 +220,6 @@
اولویت پایینگفتگوهااتاقها
-
گزارش اشکالپیوستن به اتاقنام کاربری
@@ -296,16 +294,11 @@
%d عضو%d عضو
-
-
-
-
ترک اتاقآیا از ترک این اتاق اطمینان دارید؟گپهای مستقیمدعوتبارگیری
-
رد شدنانجام شدنادیدهگرفتن
@@ -327,7 +320,6 @@
در صورت عدم پشتیبانگیری از کلیدهای خود پیش از خروج، دسترسی شما به پیامهای رمزنگاری شده از بین میرود.پیوند دائمیمشاهده منبع رمزگشایی شده
-
این کارساز خانگی میخواهد مطمئن شود که روبات نیستیدبازدرخواست کلیدهای رمزنگاری از دیگر نشستهایتان.لطفاً المنت را روی افزارهای دیگر که میتواند پیام را رمزگشایی کند، اجرا کنید تا بتواند کلیدها را به این نشست بفرستد.
@@ -335,8 +327,6 @@
قطع اتصالنپذیرفتنپالایش اعضای اتاق
-
-
عکس نمایهنام نمایشیافزودن نشانی رایانامه
@@ -419,7 +409,6 @@
افزودن کارههای ماتریکسپیام رمزنگاری شدهاتاقها
-
(پیشرفته)(پیشرفته) برپایی با کلید بازیابیگرفتن نگارش پشتیبان…
@@ -518,7 +507,6 @@
ابطالباید نشانی رایانامهٔ پیوسته به حسابتان وارد شود.شکست در تأیید نشانی رایانامه: مطمئن شوید که پیوند درون رایانامه را کلیک کردهاید
-
لطفاً سیاستهای این کارساز خانگی را بررسی کرده و بپذیرید:لطفا یک نشانی معتبر وارد کنیداین یک نشانی کارساز ماتریکس معتبر نیست
@@ -531,7 +519,6 @@
گزینش صدای زنگ برای تماسها:اطلاعاتپرش به ناخوانده
-
تحریمرفع انسداداخراج
@@ -722,7 +709,6 @@
%d پیام آگاهی نخوانده%d پیام آگاهی نخوانده
-
%1$s: %2$d پیام%1$s: %2$d پیام
@@ -796,7 +782,6 @@
ایجادخانهدعوت شد
-
غیرفعّالسازی حسابغیرفعّالسازی حسابهرگز پیامهای رمزشده را از دست ندهید
@@ -1084,7 +1069,6 @@
گرفتماطّلاعات بیشترخطای رمزگشایی
-
بازنشاندن از نشانی اصلیارتباط با مدیر خدمتتاناکنون بازبینی شود
@@ -1096,7 +1080,6 @@
رمزنگاری این اتاق پشتیبانی نمیشودلطفاً نام کاربریای وارد کنید.برای دیدن پیامهای قدیمیتر، کلیک کنید
-
پیامهای اینجا، رمزنگاری سرتاسری شدهاند.
\n
\nپیامهایتان با قفلهایی امن شدهاند و فقط شما و گیرندگان دیگر، کلیدهای یکتا را برای قفلگشاییشان دارید.
@@ -1215,7 +1198,6 @@
دعوتها، برداشتنها و انسدادها تأثیر نمیپذیرند.نمایش پیامهای پیوستن و ترک اتاقپیشنمایشی از آدرسهای URL در پیامها نمایش داده شود.
-
المنت بصورت دورهای و در بازههای قابل تنظیم در پس زمینه همگامسازی می شود.
\nاین بر مصرف باتری شما تأثیر میگذارد، یک اعلان دائمی نمایش داده میشود که المنت برای رویدادها گوش میدهد.المنت در پس زمینه همگامسازی میکند به گونه ای که منابع محدود دستگاه (باتری) حفظ میشود.
@@ -1264,7 +1246,6 @@
هیچ شماره تلفنی به حسابتان افزوده نشدهنتیجهای در پی نداشتفیلترکردن کاربران مسدود شده
-
%d مورد%d مورد
@@ -1284,19 +1265,13 @@
تنزل نقش شما در اتاق؟شما نمیتوانید این تغییر را بازگردانید. زیرا در حال ارتقای سطح کاربر دیگر به سطح خودتان هستید.
\nآیا مطمئن هستید؟
-
-
المنت برای برقراری تماس تصویری نیازمند دسترسی به میکروفون و دوربین است.
\n
\nلطفا در پنجره های بعدی دسترسی های لازم را بدهید.
-
المنت برای برقراری تماس صوتی نیازمند دسترسی به میکروفون است.
-
-
خطای SSL: هویت طرف مقابل تأیید نشد.شکست در برقراری ارتباط همزمان.
\nلطاً از مدیر کارساز بخواهید برای برقراری مطمئن تماسها، کارساز turn را پیکربندی کند.
-
بعد از راهاندازی مجدد، هیچ تاریخچه، پیام، دستگاه تائید شده یا کاربر تائید شدهای در حساب شما وجود نخواهد داشتاگر همه چیز را بازنشانی کنیدتنها در صورتی این کار را انجام دهید که از هیچ دستگاه دیگری نمیتوانید این دستگاه را تائید نمائید.
@@ -1319,7 +1294,6 @@
اگر اکنون لغو کنید، ممکن است در صورت قطع دسترسی به ورودهایتان، دادهها و پیامهای رمزنگاشته را از دست بدهد.
\n
\nهمچنین میتوانید در تنظیمات، پشتیبان امن برپا کرده و کلیدهایتان را مدیریت کنید.
-
آن را در فضای ابری خود کپی کنیدآن را روی فلش یا حافظهای دیگر ذخیره کنیدآن را چاپ کرده و در محلی امن و مطمئن نگهداری کنید
@@ -1478,7 +1452,6 @@
ارسال به عنوان پیام تباهکنندهحذفکردن از اولویت پاییناضافهکردن به اولویت پایین
-
این محتوا به عنوان محتوای نامناسب گزارش شدهاست.
\n
\nاگر نمیخواهید محتوای بیشتری از این کاربر مشاهده کنید ، می توانید او را نادیده بگیرید تا پیامهای او را مشاهده نکنید.
@@ -1553,11 +1526,8 @@
خطای نامشخص%s میخواهد نشستتان را تأیید کنددرخواست تأیید
-
-
فهمیدمتأییدشده!
-
امضاءالگوریتم
@@ -1568,7 +1538,6 @@
پشتیبانگیری از کلیدهای شما. این ممکن است چند دقیقه طول بکشد…مدیریت در بخش پشتیبانگیری از کلیدکلیدهای رمزگذاری جدید
-
کلیدهای رمزگذاری پشتیبان شما از سرور حذف شوند؟ در اینن صورت دیگر نخواهید توانست از کلید بازیابی خود برای خواندن پیام رمزشدهی قبلی خود استفاده کنید.حذف نسخهی پشتیباندر حال بررسی وضعیت نسخهی پشتیبان
@@ -1609,7 +1578,6 @@
به نظر میرسد شما در یک نشست دیگر کلید پشتیبان تهیه کردهاید. آیا میخواهید آن را با موردی که ایجاد میکنید جایگزین کنید؟از پیش، پشتیبانی روی کارساز خانگیتان وجود داردکلید بازیابی ذخیره شد.
-
کلید بازیابی خود را در جایی بسیار امن نظیر برنامههای شناختهشدهی مدیریت گذرواژه نگه داریدکلید بازیابی شما برای روز مبادا است - اگر کلید امنیتی خود را فراموش کنید می توانید از آن برای بازیابی دسترسی به پیامهای رمزگذاری شده استفاده کنید.
\nکلید بازیابی خود را در جایی بسیار امن نظیر برنامههای شناختهشدهی مدیریت گذرواژه نگه دارید
@@ -1686,13 +1654,11 @@
%d دعوتنام کارساز
-
%1$d از %2$d کلید با موفقیت بارگذاری شد.%1$d از %2$d کلید با موفقیت بارگذاری شدند.کلیدها با موفقیت بر روی دستگاه استخراج شدند
-
لطفاً یک رمز برای رمزنگاری کلیدها وارد کنید. ورود این رمز برای بارگذاری کلیدها ضروری خواهد بود.اجتماعپخش صدای شاتر
@@ -1707,13 +1673,11 @@
لطفاً ایمیل خود را بررسی کنید و روی لینک ارسال شده، کلیک کنید. پس از انجام این کار، روی ادامه کلیک کنید.برای انجام این کار اجازهی یکپارچهسازی را در تنظیمات فعال کنید.یکپارچهسازیها غیر فعال هستند
-
%1$s @ %2$sآخرین اتصالنام عمومیبهروزرسانی نام عمومیشناسه
-
المنت اطلاعاتی را جمع آوری می کند و با ارسال آنان به صورت ناشناس به ما امکان بهبود برنامه را میدهد.ارسال داده های تجزیه و تحلیلتجزیه و تحلیل
@@ -1786,7 +1750,6 @@
آغاز به گپبرونریزی بازرسیاگر اتاق فقط برای تعامل با افراد داخل سرور خانه شما میباشد، این قابلیت را فعال کنید. این تنظیم را بعدا نمیتوانید تغییر دهید.
-
یک کلید امنیتی ایجاد کنید تا در مکانی امن مانند سامانه مدیریت رمز عبور یا گاوصندوق آن را ذخیره کنید.ارتباطی با این شناسه وجود ندارد.هویت خود را تأیید کنید تا به پیامهای رمز شده دسترسی پیدا کنید.
@@ -1872,8 +1835,6 @@
هنگام انتقال تماس خطایی روی دادانتقالمتصل شوید
-
-
تماس فعال (%1$s)هنگام جستجوی شماره تلفن خطایی روی دادپد شماره گیری
@@ -2039,7 +2000,7 @@
من و همگروهیهایمیک فضای خصوصی برای نظم بخشی به اتاقهایتانفقط من
- مطمئن شوید که افراد درست به %s دسترسی دارند. میتوانید بعدها این را تغییر دهید.
+ مطمئن شوید که افراد درست به %s دسترسی دارند.ساخت یک فضاهر کسی در فضای این اتاق، میتواند اتاق را یافته و بپیوندد. فقط مدیران این اتاق می توانند به فضایی بیفزایندش.فقط اعضای فضا
@@ -2123,7 +2084,6 @@
ارتقالطفاً شکیبا باشید. ممکن است کمی زمان ببرد.پیوستن به اتاق جایگزینی
-
ناپایدارپایدارنگارش پیشگزیده
@@ -2313,7 +2273,6 @@
پرسش یا موضوع نظرسنجیایجاد نظرسنجینظرسنجی
-
فرستادن رایانامهّا و شمارههای تلفن به %sآشنایانتان خصوصی هستند. برای کشف کاربران از آشنایانتان، نیاز به اجازهتان برای فرستادن اطّلاعات آشنا به کارساز هویتتان داریم.نشست خارج شده است!
@@ -2446,4 +2405,18 @@
رونوشت از پیوند به رشتهدیدن در اتاقدیدن رشتهها
+
+ %d تغییر سطح کنترل دسترسی
+ %d تغییر سطح کنترل دسترسی
+
+ آگاهی اتاق
+ کاربران
+ آگاهی به تمام اتاق
+
+ %1$d بیشتر
+ %1$d بیشتر
+
+ نمایش کمتر
+ %1$s، %2$s و دیگران
+ %1$s و %2$s
\ No newline at end of file
diff --git a/vector/src/main/res/values-fi/strings.xml b/vector/src/main/res/values-fi/strings.xml
index 7e22ce42a8..c5e67771dd 100644
--- a/vector/src/main/res/values-fi/strings.xml
+++ b/vector/src/main/res/values-fi/strings.xml
@@ -46,7 +46,8 @@
Alkusynkronointi:
\nTuodaan huoneitaAlkusynkronointi:
-\nTuodaan liityttyjä huoneita
+\nLadataan keskustelujasi
+\nMikäli olet liittynyt moniin huoneisiin, tässä voi mennä toviAlkusynkronointi:
\nTuodaan kutsuttuja huoneitaAlkusynkronointi:
@@ -365,7 +366,7 @@
KokeellisetNämä ovat kokeellisia ominaisuuksia, jotka voivat mennä rikki. Käytä varoen.Aseta pääosoitteeksi
- Poista pääosoite
+ Kumoa pääosoitteeksi asettaminenSalauksenpurkuvirheJulkinen nimiIstunnon tunnus
@@ -520,7 +521,7 @@
yksi jäsen%d jäsentä
- Poista huoneesta
+ Poista keskustelustayksi uusi viesti%d uutta viestiä
@@ -628,7 +629,7 @@
Määritä käyttäjän oikeuksien tasoPoistaa käyttäjän operaattorioikeudetKutsuu käyttäjän nykyiseen huoneeseen
- Liittyy annettuun huoneeseen
+ Liittyy osoitteen mukaiseen huoneeseenPoistu huoneestaAseta huoneen aihePotkaisee käyttäjän pois
@@ -646,7 +647,7 @@
\nViestien näkyvyys Matrixissa on samantapainen kuin sähköpostissa. Viestiesi unohtaminen tarkoittaa, että lähettämiäsi viestejä ei näytetä uusille tai rekisteröitymättömille käyttäjille. Ne rekisteröityneet käyttäjät, joilla viestisi jo on, pääsevät kuitenkin näkemään oman kopionsa niistä jatkossakin.
Unohda kaikki viestit, jotka olen lähettänyt, kun tilini on poistettu (Varoitus: tästä seuraa, että tulevat käyttäjät näkevät vanhat keskustelut epätäydellisinä)Syötä käyttäjätunnus.
- Tämä huone on korvattu toisella huoneella
+ Tämä huone on korvattu toisella eikä ole enää aktiivinen.Keskustelu jatkuu täälläTämä huone on jatkoa toiselle keskustelullePaina tästä nähdäksesi vanhemmat viestit
@@ -801,9 +802,9 @@
%s kutsuiSinulla ei ole enempää lukemattomia viestejäKeskustelut
- Yksityisviestisi näytetään tässä. Napsauta + oikeasta alakulmasta aloittaaksesi.
+ Yksityisviestisi näytetään tässä. Napauta + oikeasta alakulmasta aloittaaksesi keskustelun.Huoneet
- Huoneesi näytetään tässä. Napsauta + oikeasta alakulmasta aloittaaksesi.
+ Huoneesi näytetään tässä. Napauta + oikeasta alakulmasta löytääksesi olemassa olevia tai perustaaksesi omiasi.ReaktiotSamaa mieltäLisää reaktio
@@ -1405,7 +1406,7 @@
ViestieditoriMuut kieletNäytä merkki poistettujen viestien paikalla
- Käytä /snow kometoa tai lähetä viesti jossa on ❄️ tai 🎉
+ Käytä /confetti-komentoa tai lähetä viesti jossa on ❄️ tai 🎉Näytä keskustelujen tehosteetNäytä poistetut viestitJos poistat käyttäjän porttikiellon, hän voi liittyä huoneeseen uudelleen.
@@ -1507,7 +1508,7 @@
Ensimmäinen synkronointi:
\nLadataan tietoja…Ensimmäinen synkronointi:
-\nOdotetaan palvelimen vastausta. . .
+\nOdotetaan palvelimen vastausta…
%1$s, %2$s, %3$s ja %4$d muu%1$s, %2$s, %3$s ja %4$d muuta
@@ -1983,4 +1984,73 @@
Yhdistä palvelimeenMinulla on jo tiliLuo tili
+ ${app_name} ei voinut käyttää sijaintiasi. Yritä myöhemmin uudelleen.
+ ${app_name} ei voinut käyttää sijaintiasi
+ Haluatko varmasti poistaa tämän kyselyn\? Et voi palauttaa sitä poistamisen jälkeen.
+ Huomaa: sovellus käynnistetään uudelleen
+ Tapahtuman sisältö
+ Tapahtuman sisältö
+ Lähetä mukautettu tapahtuma
+ Oletusluottamustaso
+ Huonetta, johon olet saanut porttikiellon ei voi avata.
+ Noudetaan yhteystietojasi…
+ Lähettää viestin lumisateen kera
+ Lähettää viestin konfetin kera
+ ${app_name} iOS
+\n${app_name} Android
+ Lähettää viestin pelkkänä tekstinä, tulkitsematta sitä markdowniksi
+ Ota yhteyttä ylläpitäjään salauksen palauttamiseksi kelvolliseen tilaan.
+ Lue koodi toisella laitteellasi tai vaihda ja lue tällä laitteella
+ Ei-luotettu kirjautuminen
+ Teit tästä kutsua edellyttävän.
+ Sijainti
+ Kysely
+
+ %1$s, %2$s ja yksi muu lukivat
+ %1$s, %2$s ja %3$d muuta lukivat
+
+ Hyväksytkö näiden tietojen lähettämisen\?
+ Versiot
+ Ohje ja tuki
+ Ohje
+ Huone on luotu, mutta joitakin kutsuja ei ole lähetetty seuraavasta syystä:
+\n
+\n%s
+ Tähän huoneeseen ei pääse tällä hetkellä.
+\nYritä myöhemmin uudelleen tai kysy huoneen ylläpitäjältä onko sinulla pääsyä.
+ Näytä huoneessa
+ Tuntematon pääsyasetus (%s)
+ Aseta osoitteita tälle huoneelle, jotta käyttäjät voivat löytää tämän huoneen kotipalvelimesi (%1$s) kautta
+ Uusi julkaistu osoite (esim. #alias:palvelin)
+ Kuka hyvänsä millä hyvänsä palvelimella voi käyttää julkaistua osoitetta huoneeseesi liittymiseen. Osoitteen julkaisemiseksi se täytyy ensin asettaa paikalliseksi osoitteeksi.
+ Kolmansien osapuolten kirjastot
+ Voit poistaa tämän käytöstä koska tahansa asetuksista
+ Emme jaa tietoa kolmansien tahojen kanssa
+ Emme tallenna tai profiloi mitään tilin tietoja
+ Huoneesta on poistuttu!
+ Sinulla ei ole lupaa päivittää rooleja, jotka vaaditaan huoneen eri osien muuttamiseen
+ Valitse roolit, jotka vaaditaan huoneen eri osien muuttamiseen
+ Tarkastele ja päivitä rooleja, jotka vaaditaan huoneen eri osien muuttamiseen.
+ %1$s, %2$s ja muita
+ %1$s ja %2$s
+ Kotipalvelinta URL-osoitteesta %s ei tavoiteta. Tarkista linkki tai valitse kotipalvelin manuaalisesti.
+ Näytä huoneessa
+ Ota käyttöön
+
+ Poistit tältä huoneelta vaihtoehtoisen osoitteen %1$s.
+ Poistit tältä huoneelta vaihtoehtoiset osoitteet %1$s.
+
+
+ %1$s poisti tältä huoneelta vaihtoehtoisen osoitteen %2$s.
+ %1$s poisti tältä huoneelta vaihtoehtoiset osoitteet %2$s.
+
+
+ Lisäsit tälle huoneelle vaihtoehtoisen osoitteen %1$s.
+ Lisäsit tälle huoneelle vaihtoehtoiset osoitteet %1$s.
+
+
+ %1$s lisäsi tälle huoneelle vaihtoehtoisen osoitteen %2$s.
+ %1$s lisäsi tälle huoneelle vaihtoehtoiset osoitteet %2$s.
+
+ Sinulla ei ole lupaa liittyä tähän huoneeseen
\ No newline at end of file
diff --git a/vector/src/main/res/values-fr-rCA/strings.xml b/vector/src/main/res/values-fr-rCA/strings.xml
index cf2ef1a13f..c54c7c6222 100644
--- a/vector/src/main/res/values-fr-rCA/strings.xml
+++ b/vector/src/main/res/values-fr-rCA/strings.xml
@@ -150,7 +150,6 @@
\nVos messages sont sécurisés avec des verrous et seuls vous et le destinataire avez les clés uniques pour les déverrouiller.
Les messages ici ne sont pas chiffrés de bout en bout.Les messages dans ce salon ne sont pas chiffrés de bout en bout.
-
Nous attendons %s…%s a été vérifiéVérifier %s
@@ -396,7 +395,6 @@
\nLes gestionnaires d’intégrations reçoivent des données de configuration et peuvent modifier des gadgets logiciels, envoyer des invitations de salon et définir des rangs à votre place.
Taille maximum pour des téléversements sur ce serveurTéléversements
-
Mot de passe oublié\?Vous n’avez aucun jeu d\'autocollants activé pour le moment.
\n
@@ -422,8 +420,6 @@
Impossible de valider le NIP, veillez en composer un nouveau.Confirmez le NIPChoisissez un NIP par sécurité
-
-
%d entrée%d entrées
@@ -476,8 +472,6 @@
Sauvegarde restaurée avec %d clé.Sauvegarde restaurée avec %d clés.
-
-
%d gadget logiciel actif%d gadgets logiciels actifs
@@ -498,7 +492,6 @@
%d salon%d salons
-
%d message notifié non lu%d messages notifiés non lu
@@ -515,8 +508,6 @@
%d seconde%d secondes
-
-
Contenu de l’évènementContenu d’évènementEnvoyer des évènements d’état personnalisés
@@ -532,21 +523,15 @@
%d nouveau message%d nouveaux messages
-
-
-
-
%d membre%d membresVoulez-vous vraiment quitter le salon\?
-
%d changement de statut%d changements de statut
-
Vous avez supprimé l’adresse alternative %1$s de ce salon.Vous avez supprimé les adresses alternatives %1$s de ce salon.
@@ -582,11 +567,9 @@
\nDésactiver votre compte ne nous fait pas oublier les messages que vous avez envoyés par défaut. Si vous souhaitez que nous oubliions vos messages, cochez la case ci-dessous.
\n
\nLa visibilité des messages dans Matrix est identique à celle des courriels. Si nous oublions vos messages, cela signifie que les messages que vous avez envoyés ne seront plus partagés avec les nouveaux utilisateurs ou les utilisateurs non enregistrés, mais les utilisateurs enregistrés qui ont déjà accès à ces messages en conserveront leur copie.
-
Impossible de vérifier l’adresse courriel : assurez-vous d’avoir cliqué sur le lien dans l’courrielAucune adresse courriel n’a été ajoutée à votre compteCette adresse courriel est déjà utilisée.
-
L’adresse courriel liée à votre compte doit être saisie.Vous n’avez pas accès à ce messageDéfinir l’avatar
@@ -739,7 +722,6 @@
Si vous annulez maintenant, vous pourrez perdre les messages et données chiffrés si vous perdez accès à vos identifiants.
\n
\nVous pouvez aussi activer la sauvegarde sécurisée et gérer vos clés dans les paramètres.
-
Copiez-le sur votre stockage dans le cloud personnelSauvegardez-le sur une clé USB ou un disque de sauvegardeImprimez-le et conservez-le en lieu sûr
@@ -765,8 +747,6 @@
Phrase de récupération%s veut vérifier votre sessionDemande de vérification
-
-
ComprisVérifié !Nouvelle invitation
@@ -780,7 +760,6 @@
Tous les salons sur le serveur %sURL du serveur d’accueilSélectionner un répertoire de salons
-
Si elles ne correspondent pas, la sécurité de votre communication est peut-être compromise.Confirmez en comparant les informations suivantes avec les paramètres utilisateur dans votre autre session :Vérifier
@@ -796,7 +775,6 @@
Gérer la sauvegarde de clésRécupération des messages chiffrésLes clés ont bien été exportées
-
Veuillez créer une phrase secrète pour chiffrer les clés exportées. Vous devrez saisir cette même phrase secrète afin de pouvoir importer les clés.ExporterExporter les clés vers un fichier local
@@ -807,7 +785,6 @@
Nom publicErreur de déchiffrementThème
-
Désactiver comme adresse principaleDéfinir comme adresse principaleCe sont des fonctionnalités expérimentales qui peuvent se comporter de façon inattendue. À utiliser avec précaution.
@@ -1014,7 +991,6 @@
Tous les messagesTous les messages (sonore)Bloquer l’utilisateur
-
Ce contenu a été signalé comme inapproprié.
\n
\nSi vous ne voulez plus voir de contenu de cet utilisateur, vous pouvez l’ignorer pour masquer ses messages.
@@ -1045,7 +1021,6 @@
Serveur d’accueilConnecté en tant queAuthentification
-
%1$s @ %2$sVu la dernière foisMettre à jour le nom public
@@ -1139,7 +1114,6 @@
Filtrer les utilisateurs exclusFiltrer les membres du salonRechercher
-
Changer le sujetMettre à niveau le salonChanger les permissions
@@ -1188,7 +1162,6 @@
Nous vous avons envoyé un courriel de confirmation à %s, consultez vos courriels et cliquez sur le lien de confirmationEnvoyer des courriels et des numéros de téléphoneVous avez donné votre autorisation pour envoyer des courriels et des numéros de téléphone à ce serveur d’identité pour découvrir d\'autres utilisateurs à partir de vos contacts.
-
Vous partagez actuellement des adresse courriels et des numéros de téléphone sur le serveur d’identité %1$s. Vous devrez vous reconnecter à %2$s pour arrêter de les partager.Acceptez les conditions de service du serveur d’identité (%s) pour vous permettre d’être découvrable avec une adresse courriel ou un numéro de téléphone.Un courriel de vérification sera envoyé à votre adresse pour confirmer la configuration de votre nouveau mot de passe.
@@ -1221,7 +1194,6 @@
%1$s a ajouté %2$s comme adresse pour ce salon.%1$s a ajouté %2$s comme adresses pour ce salon.
-
%1$s, %2$s, %3$s et %4$d autre%1$s, %2$s, %3$s et %4$d autres
@@ -1289,7 +1261,6 @@
Partager par SMSImpossible de trouver ce salon. Assurez-vous qu’il existe.Impossible d’ouvrir un salon dont vous êtes banni.
-
SignatureAlgorithmeVersion
@@ -1298,7 +1269,6 @@
On dirait que vous avez déjà configuré une sauvegarde de clé depuis une autre session. Voulez-vous la remplacer par celle que vous êtes en train de créer \?Une sauvegarde est déjà disponible sur votre serveur d’accueilLa clé de récupération a été enregistrée.
-
Enregistrer dans un fichierPartagerSauvegarder la clé de récupération
@@ -1479,7 +1449,6 @@
Impossible d\'établir une connexion en temps réel.
\nVeuillez demander à l’administrateur de votre serveur d’accueil de configurer un serveur TURN afin que les appels fonctionnent de manière fiable.Appel échoué
-
Envoyer un message vocalNouvel appel vidéoNouvel appel audio
@@ -1554,7 +1523,6 @@
Vous n\'avez pas la permission de lancer un appel dans ce salonVous n’avez pas la permission de lancer une téléconférenceVous n’avez pas la permission de lancer une téléconférence dans ce salon
-
Commencer une conversationRéinitialiserIgnorer
@@ -1588,7 +1556,6 @@
Ne perdez jamais vos messages chiffrésSécurité contre la perte d’accès aux messages et données chiffréesSauvegarde sécurisée
-
Supprimer les clés de chiffrement sauvegardées sur le serveur \? Vous ne pourrez plus utiliser votre clé de récupération pour lire l’historique des messages chiffrés.Supprimer la sauvegardeVérification de l’état de la sauvegarde
@@ -1631,7 +1598,6 @@
Veuillez en faire une copieArrêterRemplacer
-
Gérer vos paramètres de découverte.DécouverteDésactiver mon compte
@@ -1689,7 +1655,6 @@
Version de olmVersionDélai entre chaque synchronisation
-
Délai d’attente de la requête de synchronisationLancer au démarrageVous ne serez pas notifié des messages entrants quand l’application est en arrière-plan.
@@ -1843,7 +1808,7 @@
• Les serveurs correspondant à des IP littérales sont maintenant interdits.• Les serveurs correspondants à des IP littérales sont maintenant autorisés.• Les serveurs correspondant à %s sont supprimés de la liste autorisée.
- • les serveur correspondant à %s sont maintenant autorisés.
+ • les serveurs correspondant à %s sont maintenant autorisés.• Les serveurs correspondant à %s étaient supprimés de la liste des interdits.• Les serveurs correspondant à %s sont maintenant interdits.Vous avez changé les droits ACL du serveur pour ce salon.
@@ -1927,10 +1892,7 @@
${app_name} a besoin d’accéder à votre appareil photo et à votre microphone pour passer des appels vidéo.
\n
\nVeuillez autoriser l’accès dans les prochaines fenêtres pour pouvoir effectuer l’appel.
-
${app_name} a besoin d’accéder à votre microphone pour passer des appels audio.
-
-
InformationLe correspondant n’a pas décroché.Vous avez mis l’appel en attente
@@ -1966,7 +1928,6 @@
Ce n’est pas une adresse de serveur Matrix valideVeuillez saisir une URL valideVeuillez lire et accepter les politiques de ce serveur d’accueil :
-
Ce serveur d’accueil souhaite s’assurer que vous n’êtes pas un robotLe numéro de téléphone est déjà défini.Nom d’utilisateur et/ou mot de passe incorrect
@@ -2100,4 +2061,17 @@
RemarquesRemarques sur les espacesDésolé, une erreur s’est produite en essayant d’entrer dans la conférence
+ Certaines permissions manquent pour effectuer cette action, veuillez autoriser ces permissions depuis les réglages système.
+ Espaces
+ Écoute des notifications
+ Vous n’êtes pas autorisé(e) à rejoindre ce salon
+
+ %d changement des ACL du serveur
+ %d changements des ACL du serveur
+
+ Activer
+ Voir les fils de discussions
+ Permissions manquantes
+ Pour envoyer des messages vocaux, veuillez accorder la permission Microphone.
+ Pour effectuer cette action, veuillez autoriser la permission Caméra depuis les réglages système.
\ No newline at end of file
diff --git a/vector/src/main/res/values-fr/strings.xml b/vector/src/main/res/values-fr/strings.xml
index 6bae118e59..e1b3b0043c 100644
--- a/vector/src/main/res/values-fr/strings.xml
+++ b/vector/src/main/res/values-fr/strings.xml
@@ -34,7 +34,7 @@
L’appareil de l’expéditeur ne nous a pas envoyé les clés pour ce message.Envoi du message impossibleErreur de Matrix
- Adresse e-mail
+ Adresse électroniqueNuméro de téléphoneInvitation au salonSalon vide
@@ -290,7 +290,7 @@
Aucun résultatImage de profilNom affiché
- Ajouter une adresse e-mail
+ Ajouter une adresse électroniqueAjouter un numéro de téléphoneAffiche les informations de l’application dans les paramètres système.Informations sur l’application
@@ -372,11 +372,11 @@
L’application s’est arrêtée anormalement la dernière fois. Souhaitez-vous ouvrir l’écran de rapport d’anomalie \?Le rapport d’anomalie a bien été envoyéL’envoi du rapport d’anomalie a échoué (%s)
- Ceci ne ressemble pas à une adresse e-mail valide
- Cette adresse e-mail est déjà utilisée.
+ Ceci ne ressemble pas à une adresse électronique valide
+ Cette adresse électronique est déjà utilisée.Ce serveur d’accueil souhaite s’assurer que vous n’êtes pas un robot
- L’adresse e-mail liée à votre compte doit être saisie.
- Impossible de vérifier l’adresse e-mail : assurez-vous d’avoir cliqué sur le lien dans l’e-mail
+ L’adresse électronique liée à votre compte doit être saisie.
+ Impossible de vérifier l’adresse électronique : assurez-vous d’avoir cliqué sur le lien dans le courrielTrop de requêtes ont été envoyéesQuitterCiter
@@ -406,7 +406,7 @@
Quand je suis invité sur un salonParamètres utilisateur%1$s @ %2$s
- Vérifiez votre e-mail et cliquez sur le lien qu’il contient. Une fois cela fait, cliquez sur continuer.
+ Vérifiez votre courriel et cliquez sur le lien qu’il contient. Une fois ceci fait, cliquez sur continuer.Afficher tous les messages de %s \?
\n
\nVeuillez noter que cette action redémarrera l’application et pourra prendre un certain temps.
@@ -422,7 +422,7 @@
Interface utilisateurLangueChoisissez une langue
- Cette adresse e-mail est déjà utilisée.
+ Cette adresse électronique est déjà utilisée.Ce numéro de téléphone est déjà utilisé.Lancer au démarrageVider le cache des médias
@@ -533,11 +533,11 @@
Pour continuer à utiliser le serveur d’accueil %1$s, vous devez lire et accepter les conditions générales.Voir maintenantDésactiver le compte
- Votre compte sera inutilisable de façon permanente. Vous ne pourrez plus vous connecter et personne ne pourra se réenregistrer avec le même identifiant d’utilisateur. Le compte quittera tous les salons auxquels il participe et tous ses détails seront supprimés du serveur d’identité. Cette action est irréversible.
-\n
-\nDésactiver votre compte ne nous fait pas oublier les messages que vous avez envoyés par défaut. Si vous souhaitez que nous oubliions vos messages, cochez la case ci-dessous.
-\n
-\nLa visibilité des messages dans Matrix est identique à celle des e-mails. Si nous oublions vos messages, cela signifie que les messages que vous avez envoyés ne seront plus partagés avec les nouveaux utilisateurs ou les utilisateurs non enregistrés, mais les utilisateurs enregistrés qui ont déjà accès à ces messages en conserveront leur copie.
+ Votre compte sera inutilisable de façon permanente. Vous ne pourrez plus vous connecter et personne ne pourra se réenregistrer avec le même identifiant d’utilisateur. Le compte quittera tous les salons auxquels il participe et tous ses détails seront supprimés du serveur d’identité. Cette action est irréversible.
+\n
+\nDésactiver votre compte ne nous fait pas oublier les messages que vous avez envoyés par défaut. Si vous souhaitez que nous oubliions vos messages, cochez la case ci-dessous.
+\n
+\nLa visibilité des messages dans Matrix est identique à celle des courriels. Si nous oublions vos messages, cela signifie que les messages que vous avez envoyés ne seront plus partagés avec les nouveaux utilisateurs ou les utilisateurs non enregistrés, mais les utilisateurs enregistrés qui ont déjà accès à ces messages en conserveront leur copie.Veuillez oublier tous les messages que j’ai envoyé quand mon compte sera désactivé (Avertissement : les futurs utilisateurs verront une version incomplète des conversations)Désactiver le compteTélécharger
@@ -941,20 +941,20 @@
Modifier le serveur d’identitéVous utilisez actuellement %1$s pour découvrir et être découvrable par les contacts existants que vous connaissez.Vous n’utilisez actuellement aucun serveur d’identité. Pour découvrir et être découvrable par les contacts existants que vous connaissez, configurez-en un ci-dessous.
- Adresses e-mail découvrables
- Les options de découverte apparaîtront quand vous aurez ajouté un e-mail.
+ Adresses électronique découvrables
+ Les options de découverte apparaîtront quand vous aurez ajouté un courriel.Les options de découverte apparaîtront quand vous aurez ajouté un numéro de téléphone.
- La déconnexion du serveur d’identité signifie que vous ne pourrez plus être découvrable par les autres utilisateurs et que vous ne pourrez plus inviter d’autres personnes par e-mail ou par téléphone.
+ La déconnexion du serveur d’identité signifie que vous ne pourrez plus être découvrable par les autres utilisateurs et que vous ne pourrez plus inviter d’autres personnes par courriel ou par téléphone.Numéros de téléphone découvrables
- Nous vous avons envoyé un e-mail de confirmation à %s, consultez vos e-mails et cliquez sur le lien de confirmation
+ Nous vous avons envoyé un courriel de confirmation à %s, consultez vos courriels et cliquez sur le lien de confirmationRenseignez l’URL d’un serveur d’identitéImpossible de se connecter au serveur d’identitéVeuillez renseigner l’URL du serveur d’identitéLe serveur d’identité n’a pas de conditions de serviceLe serveur d’identité qui vous avez choisi n’a pas de conditions de service. Continuez uniquement si vous faites confiance au propriétaire de ce serviceUn SMS a été envoyé à %s. Saisissez le code de vérification qu’il contient.
- Vous partagez actuellement des adresse e-mails et des numéros de téléphone sur le serveur d’identité %1$s. Vous devrez vous reconnecter à %2$s pour arrêter de les partager.
- Acceptez les conditions de service du serveur d’identité (%s) pour vous permettre d’être découvrable avec une adresse e-mail ou un numéro de téléphone.
+ Vous partagez actuellement des adresses électroniques et des numéros de téléphone sur le serveur d’identité %1$s. Vous devrez vous reconnecter à %2$s pour arrêter de les partager.
+ Acceptez les conditions de service du serveur d’identité (%s) pour vous permettre d’être découvrable avec une adresse électronique ou un numéro de téléphone.Activer les journaux verbeux.Les journaux verbeux aideront les développeurs en fournissant plus de journaux quand vous envoyez un rapport d’anomalie. Même si cette option est activée, l’application n’envoie pas le contenu des messages ou toute autre donnée personnelle.Réessayez quand vous aurez accepté les termes et conditions de votre serveur d’accueil.
@@ -1049,7 +1049,7 @@
Étendez et personnalisez votre expérienceDémarrerSélectionner un serveur
- Tout comme les e-mails, les comptes ont un serveur d’accueil, même si vous pouvez parler à tout le monde
+ Tout comme les courriels, les comptes ont un serveur d’accueil, même si vous pouvez parler à tout le mondeRejoignez des millions de personnes gratuitement sur le plus grand serveur publicHébergement premium pour les organisationsEn savoir plus
@@ -1075,20 +1075,20 @@
L’application ne peut pas créer de compte sur ce serveur d’accueil.
\n
\nVoulez-vous vous inscrire en utilisant un client web \?
- Cet e-mail n’est associé à aucun compte.
+ Ce courriel n’est associé à aucun compte.Réinitialiser le mot de passe sur %1$s
- Un e-mail de vérification sera envoyé à votre adresse pour confirmer la configuration de votre nouveau mot de passe.
+ Un courriel de vérification sera envoyé à votre adresse pour confirmer la configuration de votre nouveau mot de passe.Suivant
- E-mail
+ CourrielNouveau mot de passeAttention !Le changement de mot de passe réinitialisera toutes les clés de chiffrement sur toutes vos sessions, rendant l’historique des discussions chiffrées illisible. Configurez la sauvegarde de clés ou exportez vos clés de salon depuis une autre session avant de réinitialiser votre mot de passe.Poursuivre
- Cet e-mail n’est lié à aucun compte
+ Ce courriel n’est lié à aucun compteVérifiez votre boîte de réception
- Un e-mail de vérification a été envoyé à %1$s.
+ Un courriel de vérification a été envoyé à %1$s.Touchez le lien pour confirmer votre nouveau mot de passe. Après avoir suivi le lien qu’il contient, cliquez ci-dessous.
- J’ai vérifié mon adresse e-mail
+ J’ai vérifié mon adresse électroniqueSuccès !Votre mot de passe a été réinitialisé.Vous avez été déconnecté de toutes les sessions et ne recevrez plus de notification. Pour réactiver les notifications, reconnectez-vous sur chaque appareil.
@@ -1097,10 +1097,10 @@
Votre mot de passe n’a pas encore été changé.
\n
\nArrêter le processus de changement \?
- Définir l’adresse e-mail
- Définir une adresse e-mail pour récupérer votre compte. Plus tard, vous pourrez éventuellement autoriser des personnes à vous retrouver avec votre adresse e-mail.
- E-mail
- E-mail (facultatif)
+ Définir l’adresse électronique
+ Définir une adresse électronique pour récupérer votre compte. Plus tard, vous pourrez éventuellement autoriser des personnes à vous retrouver avec votre adresse électronique.
+ Courriel
+ Courriel (facultatif)SuivantDéfinir le numéro de téléphoneDéfinir un numéro de téléphone pour autoriser éventuellement des personnes à vous découvrir.
@@ -1116,7 +1116,7 @@
Les numéros de téléphone internationaux doivent commencer par « + »Le numéro de téléphone n’a pas l’air d’être valide. Veuillez le vérifierS’inscrire sur %1$s
- Nom d’utilisateur ou e-mail
+ Nom d’utilisateur ou courrielMot de passeSuivantCe nom d’utilisateur est déjà pris
@@ -1129,8 +1129,8 @@
Sélectionner un serveur d’accueil personnaliséVeuillez compléter le captchaAcceptez les termes pour continuer
- Vérifiez vos e-mails
- Nous avons envoyé un e-mail à %1$s.
+ Vérifiez vos courriels
+ Nous avons envoyé un courriel à %1$s.
\nCliquez sur le lien qu’il contient pour continuer la création du compte.Le code saisi n’est pas correct. Veuillez vérifier.Serveur d’accueil obsolète
@@ -1184,7 +1184,7 @@
Préfixe ¯\\_(ツ)_/¯ à un message en texte brutActiver le chiffrementUne fois qu’il est activé, le chiffrement ne peut pas être désactivé.
- Le domaine de votre adresse e-mail n’est pas autorisé à s’inscrire sur ce serveur
+ Le domaine de votre adresse électronique n’est pas autorisé à s’inscrire sur ce serveurConnexion non fiableIls correspondentIls ne correspondent pas
@@ -1443,7 +1443,7 @@
Message suppriméAfficher les messages supprimésAfficher un remplaçant pour les messages supprimés
- Nous vous avons envoyé un e-mail de confirmation à %s, consultez vos e-mails et cliquez sur le lien de confirmation
+ Nous vous avons envoyé un courriel de confirmation à %s, consultez vos courriels et cliquez sur le lien de confirmationLe code de vérification n’est pas correct.MÉDIAIl n’y a aucun média dans ce salon
@@ -1466,7 +1466,7 @@
Cette opération n’est pas possible. Le serveur d’accueil est obsolète.Veuillez d’abord configurer un serveur d’identité.Veuillez d’abord accepter les termes du serveur d’identité dans les paramètres.
- Pour votre vie privée, ${app_name} prend uniquement en charge l’envoi des adresses e-mail et des numéros de téléphone hachés.
+ Pour votre vie privée, ${app_name} prend uniquement en charge l’envoi des adresses électronique et des numéros de téléphone hachés.L’association a échoué.Il n’y a actuellement aucune association avec cet identifiant.Votre serveur d’accueil (%1$s) propose d’utiliser %2$s comme serveur d’identité
@@ -1653,8 +1653,8 @@
%d utilisateur banni%d utilisateurs bannis
- Gérer les e-mails et numéros de téléphone liés à votre compte Matrix
- E-mails et numéros de téléphone
+ Gérer les courriels et numéros de téléphone liés à votre compte Matrix
+ Courriels et numéros de téléphoneSauvegarde sécuriséeDémarrer la caméraOuvrir la discussion
@@ -1677,11 +1677,11 @@
%d seconde%d secondes
- Assurez-vous d\'avoir cliqué sur le lien envoyé par e-mail.
+ Assurez-vous d\'avoir cliqué sur le lien envoyé par courriel.Supprimer %s \?Numéros de téléphone
- Aucune adresse e-mail n’a été ajoutée à votre compte
- Adresses e-mail
+ Aucune adresse électronique n’a été ajoutée à votre compte
+ Adresses électroniquesAucun numéro de téléphone n’a été ajouté à votre compteFiltrer les utilisateurs exclusNe plus ignorer cet utilisateur aura pour effet de ré-afficher ses messages.
@@ -1745,8 +1745,8 @@
%1$d de %2$dAutoriserRévoquer mon autorisation
- Vous avez donné votre autorisation pour envoyer des e-mails et des numéros de téléphone à ce serveur d’identité pour découvrir d\'autres utilisateurs à partir de vos contacts.
- Envoyer des e-mails et des numéros de téléphone
+ Vous avez donné votre autorisation pour envoyer des courriels et des numéros de téléphone à ce serveur d’identité pour découvrir d\'autres utilisateurs à partir de vos contacts.
+ Envoyer des courriels et des numéros de téléphoneSuggestionsUtilisateurs connuscode QR
@@ -1997,7 +1997,7 @@
Permettra de parcourir les salons de %sInviter dans %sPartager le lien
- Inviter par e-mail
+ Inviter par courrielVous êtes seul pour l’instant. %s sera plus agréable avec de la compagnie.Invitez des personnes dans votre espaceInviter des personnes
@@ -2153,7 +2153,7 @@
Mentions et mots-clésNotifications par défaut%s dans les paramètres pour recevoir les invitations directement dans ${app_name}.
- Lier cet e-mail à votre compte
+ Lier ce courriel à votre compteCette invitation à cette espace a été envoyée à %s qui n’est pas associé à votre compteCette invitation à ce salon a été envoyée à %s qui n’est pas associé à votre compteTous les salons dans lesquels vous vous trouvez seront affichés sur l’Accueil.
@@ -2415,4 +2415,8 @@
Copier le lien du fil de discussionVoir dans le salonVoir les fils de discussions
+
+ %d changement des ACL du serveur
+ %d changements des ACL du serveur
+
\ No newline at end of file
diff --git a/vector/src/main/res/values-in/strings.xml b/vector/src/main/res/values-in/strings.xml
index d7856089e8..719b49fc4b 100644
--- a/vector/src/main/res/values-in/strings.xml
+++ b/vector/src/main/res/values-in/strings.xml
@@ -2002,7 +2002,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan.
\n${app_name} Desktop
Atur kata sandi akun baru…Tidak dapat menyimpan file media
- Mengaktifkan pengaturan ini menambahkan FLAG_SECURE ke semua Aktifitas. Mulai ulang aplikasi ini untuk berpengaruh pada perubahannya.
+ Mengaktifkan pengaturan ini menambahkan FLAG_SECURE ke semua Aktivitas. Mulai ulang aplikasi ini untuk berpengaruh pada perubahannya.Mencegah tangkapan layar dari aplikasiKunci pemulihan kunci cadanganTidak tahu Kunci Frasa Sandi Cadangan, Anda dapat %s.
diff --git a/vector/src/main/res/values-is/strings.xml b/vector/src/main/res/values-is/strings.xml
index 07fe4b55be..ee34c9e314 100644
--- a/vector/src/main/res/values-is/strings.xml
+++ b/vector/src/main/res/values-is/strings.xml
@@ -4,9 +4,9 @@
%1$s bauð %2$s%1$s bauð þér%1$s gekk í hópinn
- %1$s hætti
+ %1$s hætti í spjallrásinni%1$s hafnaði boðinu
- %1$s sparkaði %2$s
+ %1$s fjarlægði %2$s%1$s afbannaði %2$s%1$s bannaði %2$s%1$s breyttu auðkennismynd sinni
@@ -20,10 +20,10 @@
Villa í MatrixTölvupóstfangSímanúmer
- %1$s tók til baka boð frá %2$s
+ %1$s tók til baka boð til %2$s%1$s setti birtingarnafn sitt sem %2$s%1$s breytti birtingarnafni sínu úr %2$s í %3$s
- %1$s fjarlægði birtingarnafn sitt (%2$s)
+ %1$s fjarlægði birtingarnafn sitt (sem var %2$s)%1$s breytti umræðuefninu í: %2$s%1$s breytti heiti spjallrásarinnar í: %2$s%s hringdi myndsamtal.
@@ -38,7 +38,6 @@
Tæki sendandans hefur ekki sent okkur dulritunarlyklana fyrir þessi skilaboð.Boð á spjallrás%1$s og %2$s
-
Tóm spjallrásLjóst þemaDökkt þema
@@ -80,7 +79,6 @@
SamtölEngar niðurstöðurSpjallrásir
-
Senda atvikaskráSenda hrunskrárSenda skjámynd
@@ -121,14 +119,13 @@
Taka þáttHafnaListi yfir meðlimi
-
%d meðlimur%d meðlimirFara af spjallrás
- Ertu viss um að þú viljir fara út spjallrásinni?
- BEINT SPJALL
+ Ertu viss um að þú viljir fara úr spjallrásinni\?
+ Bein skilaboðBjóða%s er að skrifa…%1$s & %2$s eru að skrifa…
@@ -145,7 +142,6 @@
LeitaSía meðlimi spjallrásarEngar niðurstöður
-
Öll skilaboðNotandamyndBirtingarnafn
@@ -180,7 +176,7 @@
Veldu tungumálBreyta lykilorðieldra lykilorð
- nýtt lykilorð
+ Nýtt lykilorðMistókst að uppfæra lykilorðLykilorðið þitt hefur verið uppfærtSýna öll skilaboð frá %s\?
@@ -199,10 +195,10 @@
ÞemaAfkóðunarvillaHeiti tækis
- Auðkenni tækis
+ Auðkenni setuDulritunarlykill tækisFlytja út
- Settu inn lykilsetningu (passphrase)
+ Settu inn lykilsetninguStaðfestu lykilsetninguFlytja innSannreyna
@@ -270,19 +266,18 @@
Þér hefur verið sparkað úr %1$s af %2$sÞú hefur verið settur í bann á %1$s af %2$sTilraunir
- Klaga efni
+ Kæra efniSlóð á heimaþjónErtu viss að þú viljir byrja raddsamtal?Ertu viss að þú viljir byrja myndsamtal?
- Fara í fyrstu ólesin skilaboð.
+ Fara í ólesiðBannaAfbannaFela öll skilaboð frá þessum notandaSýna öll skilaboð frá þessum notanda
- Þú hefur ekki heimild til að senda skilaboð á þessa spjallrás
+ Þú hefur ekki heimild til að senda skilaboð á þessa spjallrás.Gat ekki sannreynt auðkenni fjartengds þjóns.
-
- Bæta við flýtileið á aðalskjá
+ Bæta við á upphafsskjáHljóð með tilkynninguVirkja tilkynningar fyrir þennan notandaaðgangVirkja tilkynningar á þessu tæki
@@ -294,7 +289,6 @@
Heimildir fyrir tengiliðiAlltaf birta tímamerki skilaboðaBirta tímamerki á 12 stunda sniði (t.d. 2:30 fh)
-
HeimaþjónnAuðkennisþjónnÞetta tölvupóstfang er nú þegar í notkun.
@@ -304,18 +298,16 @@
Einungis meðlimir (síðan þeir skráðu sig)Innra auðkenni þessarar spjallrásarVeldu skrá yfir spjallrásir
- URL-slóð heimaþjóns
+ Heiti heimaþjóns%d ólesið tilkynnt skilaboð%d ólesin tilkynnt skilaboð
-
Ertu viss um að þú viljir eyða viðmótshlutanum?Gat ekki búið til viðmótshluta.Mistókst að senda beiðni.Boðið
- Bönun notanda mun henda þeim út úr þessu herbergi og halda þeim frá því að koma aftur.
-
+ Bann á notanda mun henda honum út af þessari spjallrás og koma í veg fyrir að viðkomandi komi aftur.Skilaboð innihalda birtingarnafn mittSkilaboð innihalda notandanafn mittSkilaboð í maður-á-mann spjalli
@@ -332,10 +324,8 @@
Þú getur ekki afturkallað þessa aðgerð, þar sem þú ert að gefa notandanum jafn mikil völd og þú hefur sjálf/ur.
\nErtu alveg viss\?Hlé milli tveggja samstillingarbeiðna
- Halda gögnum
+ Halda myndefniSkoðaðu tölvupóstinn þinn og smelltu á tengilinn sem hann inniheldur. Þegar því er lokið skaltu smella á að halda áfram.
-
-
Aðeins dulrita til sannvottaðra tækjaAldrei senda dulrituð skilaboð af þessu tæki til ósannvottaðra tækja.Völd verða að vera jákvæð heiltala.
@@ -344,36 +334,1210 @@
Vantar spjallrásarauðkenni í beiðni.Vantar notandaauðkenni í beiðni.Senda límmerki
-
Ekki var svarað á fjartengda endanum.
-
-
${app_name} þarf heimild til að nota hljóðnemann svo hægt sé að hringja hljóðsímtöl.
-
${app_name} þarf heimild til að nota myndavélina og hljóðnemann svo hægt sé að hringja myndsímtöl.
\n
\nLeyfðu aðgang í næstu sprettgluggum til þess að geta hringt.
-
-
Gera notandaaðgang óvirkannGera notandaaðganginn minn óvirkannSenda greiningargögnYfirfara núnaGera notandaaðgang óvirkannGera notandaaðgang óvirkann
-
Lýstu villunni. Hvað varstu að gera? Hverju áttirðu von á? Hvað gerðist í raun?Til að geta greint vandamál eru atvikaskrár þessa forrits sendar með þessari villuskýrslu. Ef þú vilt einungis senda textann hér fyrir ofan, taktu þá gátmerkið úr reitnum:Það er eins og þú sért að hrista símann ákveðið. Myndirðu vilja senda villuskýrslu?Forritið hrundi síðast. Myndirðu vilja senda inn villuskýrslu?Senda límmerki${app_name} safnar nafnlausum greiningargögnum til að gera okkur kleift að bæta forritið.
- Heimaskjár
+ UpphafsskjárFesta spjallrásir með óskoðuðum tilkynningumFesta spjallrásir með ólesnum skilaboðumSjálfgefið virkja forskoðun innfelldra vefslóðaÞetta eru eiginleikar á tilraunastigi sem gætu bilað á óvæntan hátt. Notist með varúð.Setja sem aðalvistfang
- Ekki setja sem aðalvistfang
+ Ekki hafa sem aðalvistfangNauðsynlegt gildi vantar.
+ Þú getur slökkt á þessu hvenær sem er í stillingunum
+ Dulrituð skilaboð í hópaspjalli
+ Dulrituð skilaboð í maður-á-mann spjalli
+ Upphaf samstillingar:
+\nHleð inn samtölunum þínum
+\nÞetta getur tekið dálítinn tíma ef þú tekur þátt í mörgum spjallrásum
+ Aðeins fólk sem hefur verið boðið getur fundið og tekið þátt
+ Einka (einungis gegn boði)
+ Þú getur sýsla- með tilkynningar í %1$s.
+ Sjálfgefinn uppruni myndefnis
+ Sjálfgefin þjöppun
+ Sýslaðu með tölvupóstföng og símanúmer sem tengd eru við Matrix-aðganginn þinn
+ Tölvupóstföng og símanúmer
+ Lykilorðið er ekki gilt
+ Utanaðkomandi aðgerðasöfn
+ Hjálpaðu okkur að bæta ${app_name}
+ Sýsla með uppgötvunarstillingarnar þínar.
+ Smelltu á leskvittanir til að sjá ítarlegan lista.
+ Birta leskvittanir
+ Markdown-sníðing
+ Láttu aðra sjá að þú sért að skrifa.
+ Senda skriftilkynningar
+ Umsýsla dulritunarlykla
+ Dulrituð hópskilaboð
+ Dulrituð bein skilaboð
+ Bestun fyrir rafhlöðuendingu
+ Birting tilkynninga
+ Tilkynningar eru óvirkar í þessari setu.
+\nYfirfarðu stillingar í ${app_name}.
+ Tilkynningar eru virkar í þessari setu.
+ Tilkynningar eru óvirkar fyrir notandaaðganginn þinn.
+\nYfirfarðu stillingar aðgangsins.
+ Tilkynningar eru virkar fyrir notandaaðganginn þinn.
+ Tilkynningar eru óvirkar í kerfisstillingum.
+\nYfirfarðu kerfisstillingarnar.
+ Tilkynningar eru virkar í kerfisstillingum.
+ Í keyrslu (%1$d af %2$d)
+ Keyra prófanir
+ Greining á vandamálum
+ Leysa vandamál með tilkynningar
+ Stikkorð mega ekki innihalda \'%s\'
+ Stikkorð mega ekki byrja með \'.\'
+ Bæta við nýju stikkorði
+ Stikkorðin þín
+ Minnst á og stikkorð
+ Virkja tilkynningar í tölvupósti fyrir %s
+ Til að fá tilkynningar í tölvupósti, þarf að tengja tölvupóstfang við Matrix-aðganginn þinn
+ Tilkynning í tölvupósti
+ Mikilvægi tilkynninga eftir atburðum
+ Skráð út úr setunni!
+ Spjallrásin hefur verið yfirgefin!
+ Einungis þar sem er minnst á og stikkorð
+ Sía bannaða notendur
+ Úr spjallþræði
+ Ábending: Ýttu lengi á skilaboð og notaðu “%s”.
+ Spjallþræðir hjálpa til við að halda samræðum við efnið og gerir auðveldara að rekja þær.
+ Haltu umræðum skipulögðum með spjallþráðum
+ Birtir alla spjallþræði sem þú hefur tekið þátt í
+ Birtir alla spjallþræði úr fyrirliggjandi spjallrás
+ Spjallþræðirnir mínir
+ Allir spjallþræðir
+ Sía þræði spjallrásar
+ Heimildir spjallrásar
+ Þessi spjallrás er ekki opinber. Þú munt ekki geta tekið aftur þátt nema að vera boðið.
+ Gefa heimild til að fá aðgang að tengiliðunum þínum.
+ Til að skanna QR-kóða þarftu að veita aðgang að myndavélinni.
+ Lýk símtali…
+ Notandi upptekinn
+ Þú settir símtalið í bið
+ %s setti símtalið í bið
+ Raddsímtal við %s
+ Myndsamtal við %s
+ Myndsamtal í gangi…
+
+ Ósvarað myndsímtal
+ %d ósvöruð myndsímtöl
+
+
+ Ósvarað raddsímtal
+ %d ósvöruð raddsímtöl
+
+ Veldu hringitón fyrir símtöl:
+ Innhringitónn
+ Nota sjálfgefinn ${app_name} hringitón fyrir innhringingar
+ Biðja um staðfestingu áður en símtal er hafið
+ Koma í veg fyrir símtöl af slysni
+ Þetta símanúmer er nú þegar skráð.
+ Því miður, ekkert utankomandi forrit hefur fundist sem getur lokið þessari aðgerð.
+ Í augnablikinu ertu ekki með neina límmerkjapakka virkjaða.
+\n
+\nBæta einhverjum við núna\?
+ Veldu hljóðtæki
+ ${app_name} símtal mistókst
+ Senda tal
+ Slóð á API-kerfisviðmót heimaþjóns
+ Ef mögulegt, skaltu skrifa lýsinguna á ensku.
+ Sýna allar spjallrásir í spjallrásalistanum, þar með taldar spjallrásir með viðkvæmu efni.
+ Sýna spjallrásir með viðkvæmu efni
+ Aðvaranir kerfis
+ Afrita tengil á spjallþráð
+ Taka úr birtingu
+ Skoða spjallþræði
+ Mistókst að fjarlægja viðmótshluta
+ Mistókst að bæta við viðmótshluta
+ Þú getur ekki byrjað símtal með sjálfum þér, bíddu eftir að þátttakendur samþykki boðið
+ Þú getur ekki byrjað símtal með sjálfum þér
+ Til að senda talskilaboð þarf að gefa heimild fyrir hljóðnema.
+ Til að framkvæma þessa aðgerð þarf að gefa heimild fyrir myndavél í kerfisstillingum.
+ Það vantar heimildir til að framkvæma þessa aðgerð, það þarf að gefa viðkomandi heimildir í kerfisstillingum.
+ Hefja talfund
+ Hefja myndfund
+ Þú hefur ekki heimildir til að hefja símtal
+ Þú hefur ekki heimildir til að hefja símtal á þessari spjallrás
+ Þú hefur ekki heimildir til að hefja fjarfund
+ Þú hefur ekki heimildir til að hefja fjarfund á þessari spjallrás
+ Vantar heimildir
+ Þú munt missa aðgang að dulrituðu skilaboðunum þínum nema þú takir öryggisafrit af dulritunarlyklum áður en þú skráir þig út.
+ Öryggisafritun dulritunarlykla í gangi. Þú munt tapa dulrituðu skilaboðunum þínum ef þú skráir þig út núna.
+ Þú munt tapa dulrituðu skilaboðunum þínum ef þú skráir þig út núna
+ Þú kveiktir á enda-í-enda dulritun.
+ %1$s kveikti á enda-í-enda dulritun.
+ Taka öryggisafrit
+ Öryggisafrita dulritunarlykla…
+ Ég vil ekki dulrituðu skilaboðin mín
+ Nota öryggisafrit af lykli
+ Hlusta eftir tilkynningum
+ Þú kveiktir á enda-í-enda dulritun (óþekkt algrími %1$s).
+ %1$s kveikti á enda-í-enda dulritun (óþekkt algrími %2$s).
+ Þú hefur bannað gestum að koma inn á spjallrásina.
+ %1$s hefur bannað gestum að koma inn á spjallrásina.
+ Þú hefur bannað gestum að koma inn á spjallrásina.
+ %1$s hefur bannað gestum að koma inn á spjallrásina.
+ Þú hefur leyft gestum að koma inn hér.
+ %1$s hefur leyft gestum að koma inn hér.
+ Þú hefur leyft gestum að koma inn á spjallrásina.
+ %1$s hefur leyft gestum að koma inn á spjallrásina.
+
+ Þú fjarlægðir varavistfangið %1$s af þessari spjallrás.
+ Þú fjarlægðir varavistföngin %1$s af þessari spjallrás.
+
+
+ %1$s fjarlægði varavistfangið %2$s af þessari spjallrás.
+ %1$s fjarlægði varavistföngin %2$s af þessari spjallrás.
+
+
+ Þú bættir við varavistfanginu %1$s fyrir þessa spjallrás.
+ Þú bættir við varavistföngunum %1$s fyrir þessa spjallrás.
+
+
+ %1$s bætti við varavistfanginu %2$s fyrir þessa spjallrás.
+ %1$s bætti við varavistföngunum %2$s fyrir þessa spjallrás.
+
+ Þú tókst til baka boð til %1$s. Ástæða: %2$s
+ %1$s tók til baka boð til %2$s. Ástæða: %3$s
+ Þú samþykktir boð um að taka þátt í %1$s. Ástæða: %2$s
+ %1$s samþykkti boð um að taka þátt í %2$s. Ástæða: %3$s
+ Þú bannaðir %1$s. Ástæða: %2$s
+ %1$s bannaði %2$s. Ástæða: %3$s
+ Þú tókst %1$s úr banni. Ástæða: %2$s
+ %1$s tók %2$s úr banni. Ástæða: %3$s
+ Þú fjarlægðir %1$s. Ástæða: %2$s
+ %1$s fjarlægði %2$s. Ástæða: %3$s
+ Þú hafnaðir boðinu. Ástæða: %1$s
+ %1$s hafnaði boðinu. Ástæða: %2$s
+ Þú hættir. Ástæða: %1$s
+ %1$s hætti. Ástæða: %2$s
+ Þú yfirgafst spjallrásina. Ástæða: %1$s
+ %1$s yfirgaf spjallrásina. Ástæða: %2$s
+ Þú tekur þátt. Ástæða: %1$s
+ %1$s tekur þátt. Ástæða: %2$s
+ Þú komst inn á spjallrásina. Ástæða: %1$s
+ %1$s kom inn á spjallrásina. Ástæða: %2$s
+ %1$s bauð þér. Ástæða: %2$s
+ Þú bauðst %1$s. Ástæða: %2$s
+ %1$s bauð %2$s. Ástæða: %3$s
+ Boð um þátttöku til þín. Ástæða: %1$s
+ Boð um þátttöku til %1$s. Ástæða: %2$s
+ Upphaf samstillingar:
+\nFlyt inn gögn úr notandaaðgangi
+ Upphaf samstillingar:
+\nFlyt inn samfélög
+ Upphaf samstillingar:
+\nFlyt inn yfirgefnar spjallrásir
+ Upphaf samstillingar:
+\nFlyt inn boð í spjallrásir
+ Upphaf samstillingar:
+\nFlyt inn spjallrásir
+ Upphaf samstillingar:
+\nFlyt inn dulritunargögn
+ Upphaf samstillingar:
+\nFlyt inn notandaaðgang…
+ Upphaf samstillingar:
+\nSæki gögn…
+ Upphaf samstillingar:
+\nBíð eftir svari frá netþjóni…
+ Þú hefur ekki heimild til að taka þátt í þessari spjallrás
+ Þú breyttir völdum %1$s.
+ Þú breyttir %1$s viðmótshluta
+ %1$s breytti %2$s viðmótshluta
+ Þú fjarlægðir %1$s viðmótshluta
+ %1$s fjarlægði %2$s viðmótshluta
+ Þú bættir við %1$s viðmótshluta
+ %1$s bætti við %2$s viðmótshluta
+ Þú samþykktir boð um að taka þátt í %1$s
+ Þú afturkallaðir boðið til %1$s
+ %1$s afturkallaði boðið til %2$s
+ Þú afturkallaðir boð til %1$s um þátttöku í spjallrásinni
+ %1$s afturkallaði boð til %2$s um þátttöku í spjallrásinni
+ Þú bauðst %1$s
+ Þú sendir boð til %1$s um þátttöku í spjallrásinni
+ Þú fjarlægðir auðkennismynd spjallrásarinnar
+ %1$s fjarlægði auðkennismynd spjallrásarinnar
+ Þú fjarlægðir umfjöllunarefni spjallrásar
+ Þú fjarlægðir heiti spjallrásar
+
+ Breyting á ACL á %d netþjóni
+ Breyting á ACL á %d netþjóni
+
+ Þú gerðir skilaboð héðan í frá sýnileg fyrir %1$s
+ Bæta við fólki
+ 🎉 Öllum netþjónum er núna bannað að taka þátt! Þessa spjallrás er ekki lengur hægt að nota.
+ • Netþjónar sem samsvara IP-tölum eru núna bannaðir.
+ • Netþjónar sem samsvara IP-tölum eru núna leyfðir.
+ • Netþjónar sem samsvara %s voru fjarlægðir af listanum yfir leyfilegt.
+ • Netþjónar sem samsvara %s eru núna leyfðir.
+ • Netþjónar sem samsvara %s voru fjarlægðir af bannlistanum.
+ • Netþjónar sem samsvara %s eru núna bannaðir.
+ Þú breyttir ACL á netþjóni fyrir þessa spjallrás.
+ %s breytti ACL á netþjóni fyrir þessa spjallrás.
+ • Netþjónar sem samsvara IP-tölum eru bannaðir.
+ • Netþjónar sem samsvara IP-tölum eru leyfðir.
+ • Netþjónar sem samsvara %s eru leyfðir.
+ • Netþjónar sem samsvara %s eru bannaðir.
+ Þú stilltir ACL á netþjóni fyrir þessa spjallrás.
+ %s stillti ACL á netþjóni fyrir þessa spjallrás.
+ Þú uppfærðir hér.
+ %s uppfærði hér.
+ Þú uppfærðir þessa spjallrás.
+ %s uppfærði þessa spjallrás.
+ %1$s gerði skilaboð héðan í frá sýnileg fyrir %2$s
+ Þú gerðir ferilskrá spjallrásar héðan í frá sýnilega fyrir %1$s
+ Þú laukst símtalinu.
+ Þú svaraðir símtalinu.
+ Þú sendir gögn til að setja upp samtalið.
+ %s sendi gögn til að setja upp samtalið.
+ Þú hringdir raddsamtal.
+ Þú hringdir myndsamtal.
+ Þú breyttir heiti spjallrásarinnar í: %1$s
+ Þú breyttir auðkennismynd spjallrásarinnar
+ %1$s breytti auðkennismynd spjallrásarinnar
+ Þú breyttir umræðuefninu í: %1$s
+ Þú fjarlægðir birtingarnafn þitt (sem var %1$s)
+ Þú breytti birtingarnafni þínu úr %1$s í %2$s
+ Þú settir birtingarnafn þitt sem %1$s
+ Opna könnun
+ Spila talskilaboð
+ Þú þarft heimild til að uppfæra spjallrás
+ Vertu þolinmóð/ur Þetta getur tekið nokkra stund.
+ Opið öllum, best fyrir dreifða hópa
+ Aðvara án hljóðs
+ Aðvara með hljóði
+ Opna emoji-tánmyndaval
+ Skipta um auðkennismynd
+ Opna viðmótshluta
+ Virkt samtal (%1$s)
+ Talnaborð
+ Nýtt PIN-númer
+ Opna notkunarskilmála %s
+ Önnur tiltæk tungumál
+ 🔐️ Vertu með mér á ${app_name}
+ Veldu þér lykilorð.
+ Veldu þér notandanafn.
+ Aðeins stutt í dulrituðum spjallrásum
+ Settu inn endurheimtulykil
+ Ný innskráning. Varst þetta þú\?
+ Flugvélahamur er virkur
+ Ekki treyst
+ Sérsniðið (%1$d) í %2$s
+ Sjálfgefið í %1$s
+ Umsjónarmaður í %1$s
+ Stjórnandi í %1$s
+ Stjórnendur
+
+ Einn aðili
+ %1$d aðilar
+
+ Aðgerðir stjórnanda
+ Ekki öruggt
+ Birta villuleitarupplýsingar á skjá
+ Aðrar setur
+ Úreltur heimaþjónn
+ Athugaðu tölvupóstinn þinn
+ Símanúmer lítur út fyrir að vera ógilt. Yfirfarðu það
+ Nota alþjóðlega sniðið.
+ Nýtt lykilorð
+ Opna valmyndina til að útbúa spjallrás
+ Settu inn slóð auðkennisþjónsins
+ Engar breytingar fundust
+ Aðrar tilkynningar frá utanaðkomandi aðilum
+ Ekkert netkerfi. Athugaðu nettenginguna þína.
+ Atburður undir umsjón stjórnanda spjallrásar
+ Eyða öryggisafriti
+ Öryggisafrit endurheimti %s !
+ Settu inn endurheimtulykil
+ Aflæsi ferli
+ Flyt inn dulritunarlykla…
+ Næ í dulritunarlykla…
+ Reikna endurheimtulykil…
+ Endurheimti úr öryggisafriti:
+ Settu inn endurheimtulykil
+ Endurheimtulykill
+ Deila endurheimtulykli með…
+ Gera afrit
+ Endurheimtulykillinn hefur verið vistaður.
+ Vista endurheimtulykil
+ Ég hef gert afrit
+ Því miður, villa kom upp
+ Smelltu hér til að sjá eldri skilaboð
+ Markdown-texti hefur verið gerður óvirkur.
+ Markdown-texti hefur verið gerður virkur.
+ Birtir upplýsingar um notanda
+ Markdown-texti af/á
+ Skilgreindu völd notanda
+ Loka á allt
+ Auðkenni viðmótshluta
+ Þemað þitt
+ Notandaauðkennið þitt
+ Vefslóð á auðkennismyndina þína
+ Birtingarnafnið þitt
+ Þessum viðmótshluta var bætt við af:
+ %1$s: %2$s %3$s
+ ** Mistókst að senda - opnaðu spjallrásina
+ %1$s í %2$s og %3$s
+
+ %1$s: %2$d skilaboð
+ %1$s: %2$d skilaboð
+
+
+ %d boð
+ %d boð
+
+ Þessi netþjónn er nú þegar á listanum
+ Fann ekki þennan netþjón eða spjallrásalista hans
+ Sláðu inn nafn nýja netþjónsins sem þú vilt skoða.
+ óþekkt IP-vistfang
+ Sýsla með öryggisafrit dulritunarlykla
+ Endurheimt dulritaðra skilaboða
+ Útflutningur dulritunarlykla tókst
+ Önnur svæði sem þú gætir ekki vitað um
+ Spila hljóð við myndatöku
+ Engin samstilling í bakgrunni
+ Bestað gagnvart rauntíma
+ Bestað gagnvart rafhleðslu
+ Hamur samstillingar í bakgrunni
+ Láta mig vita fyrir
+ Engu tölvupóstfangi hefur verið bætt við notandaaðganginn þinn
+ Engu símanúmeri hefur verið bætt við notandaaðganginn þinn
+ Mistókst að koma á rauntímatengingu.
+\nBiddu kerfisstjóra heimaþjónsins þíns um að setja upp TURN-þjón til að tryggja að símtöl virki eðlilega.
+ %1$s úr %2$s í %3$s
+ %1$s breytti völdum %2$s.
+ Stjórnandi
+ Þú breyttir auðkennismyndinni þinni
+ Þú tókst til baka boð til %1$s
+ Þú bannaðir %1$s
+ Þú afbannaðir %1$s
+ Þú fjarlægðir %1$s
+ Þú hafnaðir boðinu
+ Þú hættir í spjallrásinni
+ %1$s hætti í spjallrásinni
+ Þú hættir í spjallrásinni
+ Þú gekkst í hópinn
+ Þú gekkst í spjallrásina
+ Þú bauðst %1$s
+ Þú bjóst til umræðuna
+ %1$s bjó til umræðuna
+ Þú bjóst til spjallrásina
+ %1$s bjó til spjallrásina
+ %s gekk í hópinn.
+ Þú stilltir aðalvistfang spjallrásarinnar sem %1$s.
+ Sérsniðin kæra…
+ Sýna allar spjallrásir á forsíðu
+ Sýsla með spjallrásir og svæði
+ Sýsla með spjallrásir
+ Svæði eru ný leið til að hópa fólk og spjallrásir.
+ Bæta við fyrirliggjandi svæðum
+ Bæta við fyrirliggjandi spjallrásum
+ Yfirgefa svæði
+ Bæta við spjallrásum
+ Kanna spjallrásir
+ Búa til svæði
+ Ég og félagar í teyminu mínu
+ Bara ég
+ Einkasvæðið þitt
+ Opinbera svæðið þitt
+ Bæta við svæði
+ Einkasvæði
+ Opinbert svæði
+ Uppfærir spjallrás í nýja útgáfu
+ Búa til svæði
+ Almenningsspjallrás
+ Eyða auðkennismynd
+ Það kom upp villa við að fletta upp símanúmerinu
+ Sendir skilaboðið með snjókomu
+ Sendir skilaboðið með skrauti
+ Uppfærsla dulritunar tiltæk
+ Sendir skilaboð sem óbreyttur texti án þess að túlka það sem markdown
+ Dulritun ekki virk
+ Skilaboð í þessari spjallrás eru enda-í-enda dulrituð.
+ Kerfisstjóri netþjónsins þíns hefur lokað á sjálfvirka dulritun í einkaspjallrásum og beinum skilaboðum.
+ Stillingar spjallrásar
+ Skilaboð í þessari spjallrás eru ekki enda-í-enda dulrituð.
+ Límmerki
+ Útbý svæði…
+ Settu inn vistfang spjallrásar
+ Þetta vistfang er nú þegar í notkun
+ Vistfang svæðis
+ Eftir að kveikt er á dulritun er ekki hægt að slökkva á henni.
+ Setur ( ͡° ͜ʖ ͡°) framan við hrein textaskilaboð
+ Setur ¯\\_(ツ)_/¯ framan við hrein textaskilaboð
+ Þetta lítur ekki út eins og gilt tölvupóstfang
+ Skrá tölvupóstfang
+ Sláðu inn vistfang netþjónsins sem þú vilt nota
+ Sláðu inn vistfang Modular Element-þjóns eða netþjónsins sem þú vilt nota
+ Vistfang fyrir Element Matrix þjónustur
+ Skrá inn í %1$s
+ Tengjast við %1$s
+ Skrá inn með %s
+ Teymi
+ Vinir og fjölskylda
+ Sendir skilaboðin sem stríðni
+ Stillingar spjallrásar
+ Hunsa notanda
+ Snúa og skera utan af
+ Límmerki
+ Bæta við mynd frá
+ Búa til nýja spjallrás
+ Samþykktu þjónustuskilmála auðkennisþjónsins (%s) svo hægt sé að finna þig með tölvupóstfangi eða símanúmeri.
+ Þú ert núna að deila tölvupóstföngum eða símanúmerum á auðkennisþjóninum %1$s. Þú þarft að tengjast aftur við %2$s til að hætta að deila þessu.
+ Finnanleg tölvupóstföng
+ Búa til nýja spjallrás
+ Notaðu vélmenni, viðmótshluta og límmerkjapakka
+ Sýsla með samþættingar
+ Leyfðu \'Sýsla með samþættingar\' í stillingunum til að gera þetta.
+ Samþættingar eru óvirkar
+ Samþættingarstýring
+ Leyfa samþættingar
+ Sýna lyklaborð með tjáningartáknum
+ Senda skilaboð með \'Enter\'
+ Hefur ekki áhrif á boð/fjarlægingu/bönn.
+ Birta taka-þátt og hætta skilaboð
+ Notaðu samþættingarstýringu til að stýra vélmennum, viðmótshlutum og límmerkjapökkum.
+\nSamþættingarstýringar taka við stillingagögnum og geta breytt viðmótshlutum, sent boð í spjallrásir, auk þess að geta úthlutað völdum fyrir þína hönd.
+ Samþættingar
+ Þetta er upphaf ferils beinna skilaboða með %s.
+ Bein skilaboð
+ Leita að heiti
+ Leita eftir heiti, auðkenni eða tölvupóstfangi
+ Nafn eða auðkenni (#example:matrix.org)
+ Skoða spjallrásalistann
+ Senda ný bein skilaboð
+ Breytingar á skilaboðum
+ Þjappa myndskeiði %d%%
+ Þjappa mynd…
+ Sendi skrá (%1$s / %2$s)
+ Dulrita skrá…
+ Öll samfélög
+ Sýna fjarlægð skilaboð
+ Þú átt engin fleiri ólesin skilaboð
+ Boðið af %s
+ Sendi þér boð
+ Svara í spjallþræði
+ Allir lyklar öryggisafritaðir
+ Setja upp á þessu tæki
+ Varið öryggisafrit
+ Búa til svæði
+ Einungis gegn boði, best fyrir þig og lítinn hóp
+ Fara í fyrstu leskvittun
+ Sannprófa þessa setu
+ Þau samsvara ekki
+ Þau samsvara
+ Fela ítarlegt
+ Birta ítarlegt
+ Hreinsa öll gögn
+ Þú hefur verið skráður út úr öllum setum og munt ekki lengur fá ýti-tilkynningar. Til að endurvirkja tilkynningar, þarf að skrá sig aftur inn á hverju tæki fyrir sig.
+ Eigðu samtölin þín.
+ Aftengja auðkennisþjón
+ Umsagnir um svæði
+ Birta frátökutákn fyrir fjarlægð skilaboð
+ Eftir að þetta hefur verið virkjað, muntu geta sent staðsetninguna þína á hvaða spjallrás sem er
+ Niðurstöður birtast einungis eftir að þú hefur lokað könnuninni
+ Kjósendur sjá niðurstöðurnar þegar þeir hafa kosið
+
+ Lokaniðurstöður byggðar á %1$d atkvæði
+ Lokaniðurstöður byggðar á %1$d atkvæðum
+
+
+ %1$d atkvæði greitt. Greiddu atkvæði til að sjá útkomuna
+ %1$d atkvæði greidd. Greiddu atkvæði til að sjá útkomuna
+
+ Næ ekki að tengjast heimaþjóni á þessari slóð, athugaðu slóðina
+ réttur valkostur
+ Spurning eða viðfangsefni
+ Endurræstu forritið til að breytingin taki gildi.
+ Virkja LaTeX-stærðfræði
+ Tengja þetta tölvupóstfang við notandaaðganginn þinn
+
+ %1$d til viðbótar
+ %1$d til viðbótar
+
+ Birta skilaboðablöðrur
+ Mistókst að hlaða inn landakorti
+ Myndgera staðsetningu notenda á tímalínunni
+ Virkja deilingu staðsetninga
+ ${app_name} gat ekki fengið staðsetninguna þína. Reyndu aftur síðar.
+ ${app_name} gat ekki fengið staðsetninguna þína
+ Lokuð könnun
+ Ljúka könnun
+ Ljúka þessari könnun\?
+ Ljúka könnun
+ Engin atkvæði greidd
+
+ Byggt á %1$d atkvæði
+ Byggt á %1$d atkvæðum
+
+
+ %1$d atkvæði
+ %1$d atkvæði
+
+
+ Það þarf allavega %1$s valkost
+ Það þarf allavega %1$s valkosti
+
+ Spurning má ekki vera auð
+ Set upp öryggisafrit af lykli
+ Útbý öruggislykil úr lykilsetningu
+ Lykilsetning endurheimtu
+ Notaðu lykilsetningu endurheimtu eða dulritunarlykil
+ Sýsla með í öryggisafriti dulritunarlykla
+ Nota öryggisafrit af lykli
+ Verja öryggisafrit
+ Eyða öryggisafriti
+ Athuga ástand öryggisafrits
+ Eyði öryggisafriti…
+ Öryggisafrit af lyklum er ekki virkt í þessari setu.
+
+ %d nýjum lykli hefur verið bætt við þessa setu.
+ %d nýjum lyklum hefur verið bætt við þessa setu.
+
+
+ Endurheimti öryggisafrit með %d lykli.
+ Endurheimti öryggisafrit með %d lyklum.
+
+ Ef þú veist ekki lykilsetningu fyrir endurheimtu, geturðu %s.
+ notað endurheimtulykilinn þinn
+ Öryggisafrit er þegar til staðar á heimaþjóninum þínum
+ (Ítarlegt) Settu upp með endurheimtulykli
+ Bý til öryggisafrit
+ Stilla lykilsetningu
+ Verðu öryggisafritið þitt með lykilsetningu.
+ Byrja að nota öryggisafrit dulritunarlykla
+ Lykilsetning er of veik
+ Settu inn lykilsetningu
+ Lykilsetningar samsvara ekki
+ Búa til lykilsetningu
+ Útbúðu lykilsetningu til að dulrita útfluttu dulritunarlyklana. Þú þarft að setja inn sama lykilsetningu til að geta flutt aftur inn þessa dulritunarlykla.
+ Renna til að ljúka símtalinu
+ Tapaðu aldrei dulrituðum skilaboðum
+ Endilega %s til að halda áfram að nota þessa þjónustu.
+ Endilega %s til að fá þessi takmörk hækkuð.
+ Þessi heimaþjónn er kominn fram yfir takmörk á mánaðarlega virkum notendum.
+ Þessi heimaþjónn er kominn fram yfir takmörk á mánaðarlega virkum notendum þannig að sumir notendur munu ekki geta skráð sig inn.
+ Þessi heimaþjónn er kominn fram yfir takmörk á tilföngum sínum.
+ Þessi heimaþjónn er kominn fram yfir takmörk á tilföngum sínum þannig að sumir notendur munu ekki geta skráð sig inn.
+ hafðu samband við kerfisstjóra þjónustunnar þinnar
+ Þessi spjallrás er framhald af öðru samtali
+ Samtalið heldur áfram hér
+ Þessari spjallrás hefur verið skipt út og er hún ekki lengur virk.
+ Til að halda áfram að nota %1$s heimaþjóninn þarftu að yfirfara og samþykkja skilmálana og kvaðir.
+ Til að laga umsýslu Matrix-forrita
+ Beiðni um deilingu dulritunarlykils
+ Þú verður að samþykkja þjónustuskilmálana til að geta haldið áfram.
+ Ræstu myndavél kerfisins í stað sérsniðna myndavélaskjásins.
+ Þessi viðmótshluti vill nota eftirfarandi tilföng:
+ Fara af fyrirliggjandi fjarfundi og skipta yfir í hinn\?
+ Því miður, villa kom upp við að reyna að tengjast fjarfundinum
+ Því miður, fjarfundasímtöl með Jitsi eru ekki studd á eldri tækjum (tæki með Android OS minna en 6.0)
+ Afturkalla aðgang fyrir mig
+ Mistókst að hlaða inn viðmótshluta.
+\n%s
+ Að nota það gæti deilt gögnum með %s:
+ Að nota það gæti stillt vefkökur og deilt gögnum með %s:
+ Ef þetta samsvarar ekki, getur verið að samskiptin þín séu berskjölduð.
+ Staðfestu með því að bera eftirfarandi saman við \'Stillingar notanda\' í hinni setunni þinni:
+
+ Tókst að flytja inn%1$d/%2$d dulritunarlykli.
+ Tókst að flytja inn%1$d/%2$d dulritunarlyklum.
+
+ Veldu hvaða svæði hafa aðgang að þessari spjallrás. Ef svæði er valið geta meðlimir þess fundið og tekið þátt í spjallrásinni.
+ Hver sem er á svæði með þessari spjallrás getur fundið hana og tekið þátt í henni. Aðeins stjórnendur spjallrásarinnar geta bætt henni í svæði.
+ Hver sem er getur látið vita af sér á spjallrásinni, meðlimir geta þá samþykkt eða hafnað
+ Mistókst að fá sýnileika spjallrásar á spjallrásaskrá (%1$s).
+ Svæði sem þú veist að innihalda þessa spjallrás
+ Veldu hverjir geta fundið spjallrásina og tekið þátt.
+ Svæði sem hafa aðgang
+ Leyfa meðlimum svæðis að finna og fá aðgang.
+ Meðlimir svæðisins %s geta fundið, forskoðað og tekið þátt.
+ Óþekkt aðgangsstilling (%s)
+ Birta þessa spjallrás opinberlega á skrá %1$s yfir spjallrásir\?
+ Einungis meðlimir svæðis
+ Hver sem er getur fundið svæðið og tekið þátt
+ Hver sem er getur fundið spjallrásina og tekið þátt
+ Birta falda atburði í tímalínu
+ Hjálp og um
+ Rödd og myndband
+ Stillingar spjallrásar
+ Umfjöllunarefni spjallrásar (valkvætt)
+ Skipta um netkerfi
+ Búa til nýtt svæði
+ Viðbrögð
+ Skoða viðbrögð
+ Bæta við viðbrögðum
+ Viðbrögð
+ Þú hefur klárað að lesa allt!
+ Skoða á spjallrás
+ Breytir auðkennismyndinni þinni einungis í fyrirliggjandi spjallrás
+ Breytir auðkennismyndinni einungis í fyrirliggjandi spjallrás
+ Breytir birtu gælunafni þínu einungis í fyrirliggjandi spjallrás
+ Fjarlægir notanda með uppgefið auðkenni úr þessari spjallrás
+ Stilla umfjöllunarefni spjallrásar
+ Gengur til liðs við spjallrás með uppgefnu vistfangi
+ Býður notanda með uppgefið auðkenni í fyrirliggjandi spjallrás
+ Stillir heiti spjallrásar
+ Hunsar notanda, felur skilaboð viðkomandi fyrir þér
+ Bannar notanda með uppgefið auðkenni
+ Engir virkir viðmótshlutar
+ Nota hljóðnemann
+ Nota myndavélina
+ Hlaða inn viðmótshluta
+ Nýtt boð
+ Netþjónninn þinn
+ Útgáfa spjallrásar
+
+ %d bannaður notandi
+ %d bannaðir notendur
+
+ %1$s, %2$s, %3$s og %4$s
+ Villa í SSL.
+ Veldu heimaþjón
+ Skrá inn með einfaldri innskráningu (single sign-on)
+ Nota sem sjálfgefið og ekki spyrja aftur
+ Kveikja á HD
+ Slökkva á HD
+ Skipta á milli myndavéla
+ Þráðlaus heyrnartól
+ Tilkynning á spjallrás
+ Notendur
+ Tilkynna öllum á spjallrásinni
+ Sýna minna
+ Deila staðsetningu
+ Búa til könnun
+ Opna tengiliði
+ Senda límmerki
+ Hlaða inn skrá
+ Senda myndir og myndskeið
+ Opna myndavél
+ Opna með
+ Deila staðsetningu
+ Landakort
+ Deila staðsetningu
+ Staðsetning
+ Deila staðsetningu
+ Tegund könnunar
+ Breyta könnun
+ Fjarlægja könnun
+ Atkvæði greitt
+ ÚTBÚA KÖNNUN
+ BÆTA VIÐ VALKOSTI
+ Búa til valkosti
+ Búa til könnun
+ %1$ds eftir
+ Eyða upptöku
+ Stöðva upptöku
+ Uppfærsla er nauðsynleg
+ Uppfæra
+ Nafnlaus spjallrás
+ Tillaga
+ Ljúka uppsetningu
+ Sleppa í bili
+ Deila tengli
+ Bjóða fólki
+ Lýsing
+ Slembið
+ Almennt
+ Einka
+ Opinbert
+ Eyða ósendum skilaboðum
+ Mistókst
+ Sent
+ Sendi
+ Atburður sendur!
+ Ekkert efni
+ Stöðulykill
+ Tegund
+ Senda sérsniðinn atburð
+ Skoða stöðu spjallrásar
+ Ekki tiltækt
+ Ónettengt
+ Nettengt
+ Ekki tilkynna
+ Ekki skoðað
+ Athugað
+ Valið
+ Myndskeið
+ Mynd
+ Skjámynd
+ Tókst ekki að auðkenna
+ Óþekktur einstaklingur
+ Notendur
+ Flutningur
+ Tengjast
+ Virkt samtal (%1$s) ·
+
+ Virkt samtal ·
+ %1$d virk samtöl ·
+
+ Ekkert svar
+ Innhringing myndsamtals
+ Innhringing raddsamtals
+ Hringja til baka
+ Þessu símtali er lokið
+ Henda breytingum
+ Breyta PIN-númeri
+ Virkja PIN-númer
+ Gleymt PIN-númer\?
+ Settu inn PIN-númerið þitt
+ Staðfestu PIN-númer
+
+ %d færsla
+ %d færslur
+
+ Tengiliðaskrá
+ KANNA NÁNAR
+ NÁÐI ÞVÍ
+ Stilla auðkennismynd
+ Umfjöllunarefni
+ Nafn spjallrásar
+ Setja upp
+ Ræsa myndavélina
+ Stöðva myndavélina
+ Kveikja á hljóðnema
+ Þagga niður í hljóðnema
+ Opna spjall
+ Hlutverk
+ Stilla hlutverk
+ Senda inn
+ Nota %1$s
+ Núverandi tungumál
+ Bjóða vinum
+ Bjóða notendum
+ BJÓÐA
+ Ódulritað
+ Frumstilla allt
+ Gat ekki vistað myndefnisskrá
+ Skilaboð…
+ Leysa vandamál
+ "Umfjöllunarefni: "
+ Dulritun virk
+ Ljúka
+ Hætt við staðfestingu
+ Endurlesa
+ Staðfesta fjarlægingu
+ Fjarlægja…
+ Tenging við netþjón hefur rofnað
+ Nei
+ Já
+ QR-kóði
+ Endurstilla dulritunarlykla
+ Treyst
+ Setur
+ Aðvörun
+ Sannreynt
+ Sannreyna
+ óstöðug
+ stöðug
+ Sjálfgefin útgáfa
+ Útgáfa á þjóni
+ Heiti þjóns
+ Virkja dulritun
+ Virkja dulritun\?
+ Tímalína
+ Hætta að hunsa
+ Notendur
+ Boðsgestir
+ Sérsniðið
+ Umsjónarmenn
+ Fara út
+ Fara af spjallrás
+ Innsendingar
+ Tilkynningar
+ Stillingar
+ Meira
+ Kanna nánar
+ Öryggi
+ Bíð…
+ Könnun
+ Skrá
+ Tal
+ Hljóð
+ Mynd.
+ Myndskeið.
+ Virkja dulritun
+ Núverandi seta
+ Stillingar
+ Ítarlegar stillingar
+ Lýsingin er of stutt
+ Hreinsa gögn
+ Lykilorð
+ Skrá inn
+ Skrá inn
+ Matrix-auðkenni
+ Aðvörun
+ Næsta
+ Lykilorð
+ Notandanafn
+ Notandanafn eða tölvupóstfang
+ Næsta
+ Settu inn kóða
+ Staðfestu símanúmer
+ Næsta
+ Símanúmer (valfrjálst)
+ Símanúmer
+ Næsta
+ Tölvupóstfang (valfrjálst)
+ Tölvupóstur
+ Könnuninni er lokið
+ Valkostur %1$d
+ Spurning eða viðfangsefni könnunar
+ Aðvörun
+ Lykilorðið þitt hefur verið endurstillt.
+ Tókst!
+ Ég hef staðfest tölvupóstfangið mitt
+ Halda áfram
+ Aðvörun!
+ Tölvupóstur
+ Næsta
+ Vistfang
+ Hreinsa vinnsluferil
+ Skrá inn
+ Nýskrá
+ Halda áfram
+ einfaldri innskráningu (single sign-on)
+ Skrá inn með %s
+ Halda áfram með %s
+ Eða
+ Annað
+ Kanna nánar
+ Ég er nú þegar með notandaaðgang
+ Stofna aðgang
+ Komast í gang
+ Tengjast þjóni
+ Samfélög
+ Ólesin skilaboð
+ Fjarlægja úr eftirlætum
+ Bæta í eftirlæti
+ Stillingar
+ Þagga niður
+ Aðeins minnst á
+ Öll skilaboð
+ Öll skilaboð (hávært)
+ Tilkynnt sem óviðeigandi
+ Tilkynnt sem ruslpóstur
+ Efni tilkynnt
+ KÆRA
+ Ástæður fyrir kæru á þessu efni
+ Kæra þetta efni
+ Þetta er óviðeigandi
+ Þetta er ruslpóstur
+ %1$s kl. %2$s
+ SKRÁR
+ MYNDEFNI
+ %1$d af %2$d
+ Staðsetning
+ Könnun
+ Myndasafn
+ Myndavél
+ Tengiliður
+ Skrá
+ Opna leiðsagnarsleðann
+ Kóði
+ Auðkennisþjónn
+ Þjónustuskilmálar
+ Skoða breytingaskrá
+ Tillögur
+ QR-kóði
+ Tengill afritaður á klippispjald
+ (breytt)
+ Bíð…
+ Bein skilaboð
+ Gefðu umsögn
+ Umsagnir
+ Kerfisstillingar
+ Útgáfur
+ Hjálp og aðstoð
+ Hjálp
+ Snið:
+ Slóð:
+ Öryggi og gagnaleynd
+ Kjörstillingar
+ Almennt
+ Opinbert
+ Umfjöllunarefni
+ Heiti
+ Nafn spjallrásar
+ ÚTBÚA
+ Bein skilaboð
+ Spjallrásir
+ Bíddu aðeins…
+ Búa til nýja spjallrás
+ Skilaboðum eytt
+ Spjallrásir
+ Samtöl
+ Reyna aftur
+ Svara
+ Breyta
+ Óþekkt villa
+ Náði því
+ Sannreynt!
+ Undirritun
+ Reiknirit
+ Útgáfa
+ Endurheimta úr öryggisafriti
+ Ertu viss\?
+ Óvænt villa
+ Stöðva
+ Skipta út
+ Vista sem skrá
+ Deila
+ Lokið
+ Tókst !
+ (Ítarlegt)
+ %d+
+ %1$s: %2$s
+ fella saman
+ fletta út
+ Settu inn lykilorðið þitt.
+ Settu inn notandanafn.
+ Þögult
+ Breytir birtu gælunafni þínu
+ Fara af spjallrás
+ Birtir aðgerð
+ Hunsa
+ Deila
+ Lesa DRM-varið myndefni
+ Leyfa
+ Auðkenni spjallrásar
+ Opna í vafra
+ Endurlesa viðmótshluta
+ Viðmótshluti
+ Virkir viðmótshlutar
+ SKOÐA
+ %1$s: %2$s
+ Ég
+ Ný skilaboð
+ Spjallrás
+ Nýr atburður
+ %1$s og %2$s
+
+ %d tilkynning
+ %d tilkynningar
+
+ Bæta við nýjum þjóni
+ Opinbert
+ Einka
+ Staðvær vistföng
+ Gefa út
+ Aðgangur að spjallrás
+ Stillingar notandaaðgangs
+ Veldu
+ Veldu
+ Myndefni
+ Lykilorð
+ hér
+ Forskoða myndefni fyrir sendingu
+
+ %d sekúnda
+ %d sekúndur
+
+ Skilaboð frá vélmennum
+ Boð á spjallrás
+ Stikkorð
+ \@spjallrás
+ Hópskilaboð
+ Bein skilaboð
+ Notandanafnið mitt
+ Birtingarnafn mitt
+ Virkja í ræsingu
+ Bæta við notandaaðgangi
+ Sérsniðnar stillingar.
+ Virkja
+ Setustillingar.
+ Virkja
+ Stillingar notandaaðgangs.
+ Opna stillingar
+ Kerfisstillingar.
+ Annað
+ Sjálfgefnar tilkynningar
+ Ítarlegar stillingar á tilkynningum
+ Fjarlægja %s\?
+ Símanúmer
+ Tölvupóstföng
+ Ekkert
+ Sía
+ Spjallþræðir
+ Spjallþráður
+
+ %d valið
+ %d valið
+
+ Breyta stillingum
+ Bjóða notendum
+ Heimildir
+ %1$s og %2$s
+ Taka notanda úr banni
+ Banna notanda
+ Fjarlægja notanda
+ Lækka niður um stig
+ Ekkert svar
+ Bíða
+ Halda áfram
+ Símtöl
+ Alltaf spyrja
+ Aftan
+ Fram
+ Heyrnartól
+ Hátalari
+ Sími
+ Svæði
+ Skrá yfir spjallrásir
+ Ekki fleiri niðurstöður
+ Tilkynningar
+ Nýtt gildi
+ Tókst
+ Villa
+ Endurstilla
+ Hafna
+ Spila
+ Aftengjast
+ Afturkalla
+ Sækja
+ Hafna
+ Hunsa
+ Sleppa
+ Samþykkja
+ Breyta
+ Samþykki
+ Ekki núna
+ Virkja
+ Skipta um
+ Bæta við
+ Ýttu til að breyta svæðum
+ Veldu svæði
+ Hætta að birta þetta vistfang
+ Birta þetta vistfang
+ Bæta við staðværu vistfangi
+ Þessi spjallrás er ekki með nein staðvær vistföng
+ Stilltu vistföng fyrir þessa spjallrás svo notendur geti fundið hana í gegnum heimaþjóninn þinn (%1$s)
+ Nýtt birt vistfangs (t.d. #samnefni:netþjónn)
+ Engin önnur birt vistföng ennþá.
+ Engin önnur birt vistföng ennþá, bættu einu við hér fyrir neðan.
+ Eyða vistfanginu \"%1$s\"\?
+ Hætta að birta vistfangið \"%1$s\"\?
+ Birta nýtt vistfang handvirkt
+ Önnur birt vistföng:
+ Þetta er aðalvistfangið
+ Birt vistföng getur hvaða einstaklingur eða netþjónn sem er notað til að taka þátt í spjallrásinni þinni. Til að birta vistfang, þarf fyrst að stilla það sem staðvært vistfang.
+ Birt vistföng
+ Sjá og sýsla með vistföng þessa svæðis.
+ Vistföng svæða
+ Sjá og sýsla með vistföng þessarar spjallrásar og sýnileika hennar í spjallrásaskránni.
+ Vistföng spjallrása
+ Leyfa gestum að taka þátt
+ Aðgangur að svæði
+ Hver hefur aðgang\?
+ Láta mig vita fyrir
+ Uppgötvun
+ Uppfærslur spjallrásar
+ Skilaboð sem innihalda @spjallrás
+ Þegar spjallrásir eru uppfærðar
+ Heimildir svæðis
+ Ástæða fyrir banni
+ Ástæða fjarlægingar
+ Hætta við boð
+ Hætta að hunsa notanda
+ Hunsa notanda
+ Lækka þig sjálfa/n í tign\?
+ Fjarlægja úr spjalli
+ Hætta við boð
+ Notandinn sem þú hringdir í er upptekinn.
+ Þetta er ekki gilt vistfang á Matrix-þjóni
+ Tillögur að spjallrásum
+ Skoða á spjallrás
+ Þú breyttir vistföngum fyrir þessa spjallrás.
+ %1$s breytti vistföngum fyrir þessa spjallrás.
+ Þú breytti aðal- og varavistföngunum fyrir þessa spjallrás.
+ %1$s breytti aðal- og varavistföngunum fyrir þessa spjallrás.
+ Þú breyttir varavistfanginu fyrir þessa spjallrás.
+ %1$s breytti varavistfanginu fyrir þessa spjallrás.
+ Þú fjarlægðir aðalvistfang spjallrásarinnar.
+ %1$s fjarlægði aðalvistfang spjallrásarinnar.
+ %1$s stillti aðalvistfang spjallrásarinnar sem %2$s.
+ Þú bættir við %1$s og fjarlægðir %2$s sem vistföng fyrir þessa spjallrás.
+ %1$s bætti við %2$s og fjarlægði %3$s sem vistföng fyrir þessa spjallrás.
+
+ Þú fjarlægðir %1$s sem vistfang fyrir þessa spjallrás.
+ Þú fjarlægðir %1$s sem vistföng fyrir þessa spjallrás.
+
+
+ %1$s fjarlægði %2$s sem vistfang fyrir þessa spjallrás.
+ %1$s fjarlægði %2$s sem vistföng fyrir þessa spjallrás.
+
+
+ Þú bættir við %1$s sem vistfangi fyrir þessa spjallrás.
+ Þú bættir við %1$s sem vistföngum fyrir þessa spjallrás.
+
+
+ %1$s bætti við %2$s sem vistfangi fyrir þessa spjallrás.
+ %1$s bætti við %2$s sem vistföngum fyrir þessa spjallrás.
+
+ Breyta umfjöllunarefni
+ Uppfæra svæðið
+ Uppfæra spjallrásina
+ Senda m.room.server_acl atburði
+ Breyta heimildum
+ Breyta nafni svæðis
+ Breyta nafni spjallrásar
+ Breyta sýnileika ferils
+ Virkja dulritun svæðis
+ Virkja dulritun spjallrásar
+ Skipta um aðalvistfang svæðisins
+ Skipta um aðalvistfang spjallrásarinnar
+ Skipta um táknmynd svæðis
+ Skipta um auðkennismynd spjallrásar
+ Breyta viðmótshlutum
+ Tilkynna öllum
+ Fjarlægja skilaboð send af öðrum
+ Banna notendur
+ Fjarlægja notendur
+ Senda skilaboð
+ Sjálfgefið hlutverk
+ %1$s, %2$s og aðrir
+ Hringing…
+ Afrita
+ Merkja sem lesið
+ Ertu viss um að þú viljir skrá þig út\?
+ Leggja á
+ Hafna
+ Samþykkja
+ Lokið
+ Svæði
+ Hefja spjall
+ Ekkert
+ Ertu viss\?
+ Öryggisafrit af lykli
+ Sjálfgefið í kerfinu
+ Sendi skilaboð…
+ Skilaboð send
+ Tóm spjallrás (var %s)
+
+ %1$s, %2$s, %3$s og %4$d til viðbótar
+ %1$s, %2$s, %3$s og %4$d til viðbótar
+
+ %1$s, %2$s og %3$s
+ Sérsniðið
+ Sérsniðið (%1$d)
+ Sjálfgefið
+ Umsjónarmaður
+ %1$s bauð %2$s
+ Engin breyting.
+ %1$s gekk í hópinn
+ Boðið þitt
\ No newline at end of file
diff --git a/vector/src/main/res/values-iw/strings.xml b/vector/src/main/res/values-iw/strings.xml
index 73a57823eb..b70034888f 100644
--- a/vector/src/main/res/values-iw/strings.xml
+++ b/vector/src/main/res/values-iw/strings.xml
@@ -203,7 +203,7 @@
יעדי התראותניהול מפתחות קריפטוגרפיהקריפטוגרפיה
- השתמש במנהל שילוב לניהול בוטים, גשרים, ווידג\'טים וחבילות מדבקות.
+ השתמש במנהל אינטגרציה לניהול בוטים, גשרים, ווידג\'טים וחבילות מדבקות.
\nמנהלי אינטגרציה מקבלים נתוני תצורה ויכולים לשנות ווידג\'טים, לשלוח הזמנות לחדר ולהגדיר רמות כוח מטעמכם.אינטגרציותמתקדם
@@ -440,7 +440,7 @@
חסום הכלאפשריישומון זה רוצה להשתמש במשאבים הבאים:
- מצטערים, שיחות ועידה עם Jitsi אינן נתמכות במכשירים ישנים (מכשירים עם מערכת הפעלה אנדרואיד מתחת ל -5.0)
+ מצטערים, שיחות ועידה עם Jitsi אינן נתמכות במכשירים ישנים (מכשירים עם מערכת הפעלה אנדרואיד מתחת ל -6.0)מזהה חדרמזהה ישומוןערכת הנושא שלכם
@@ -515,7 +515,7 @@
כל החדרים המקומיים %sכל החדרים בשרת %s
- כתובת אתר של שרת בית
+ שם השרתבחר מדריך חדריםאם הם לא תואמים, אבטחת התקשורת שלך עלולה להיפגע.אשרו על ידי השוואה בין הדברים הבאים להגדרות המשתמש בפגישה האחרת שלכם:
@@ -686,7 +686,7 @@
בועט משתמש עם מזהה נתוןהגדר את נושא החדרעזוב חדר
- מצטרף לחדר עם כינוי נתון
+ מצטרף לחדר עם כתובת ידועהמזמין משתמש עם זיהוי נתון לחדר הנוכחימשתמש מבוטל עם מזהה נתוןהגדר את רמת ההרשאה של המשתמש
@@ -705,7 +705,7 @@
רטוט בעת אזכור משתמשכולל שינויים באווטאר ושמות תצוגה.הצג אירועי חשבון
- הזמנות, בעיטות ואיסורים אינם מושפעים.
+ הזמנות, הסרות ואיסורים אינם מושפעים.הראה אירועי הצטרפות ועזיבהלחץ על אישורי הקריאה לרשימה מפורטת.הצג קבלות הצג קבלות קריאה
@@ -2099,8 +2099,8 @@
שיחה פעילה ·%1$d שיחות פעילות ·
-
-
+
+ שיחה פעילה (%1$s)אירעה שגיאה בחיפוש מספר הטלפון
@@ -2124,17 +2124,17 @@
להודיע לכל החדר%1$d יותר
-
-
-
+
+
+ %1$s, %2$s ואחרים%1$s ו %2$s%d שינוי ברשימות ACL בשרתים
-
-
-
+
+
+ נהל חדריםהחלט מי יכול לראות ולהצטרף לחדר זה.
@@ -2175,4 +2175,246 @@
שם המשתמש שליהזמנות לחדרמילות מפתח
+ הזמן אל %s
+ הזמן אנשים
+ הזמן אנשים למרחב שלך
+ תֵאוּר
+ יוצר מרחב…
+ אַקרַאִי
+ ראשי
+ בואו ניצור חדר לכל אחד מהם. אתה יכול להוסיף עוד מאוחר יותר, כולל אלה שכבר קיימים.
+ על איזה דברים אתה עובד\?
+ ודא שלאנשים הנכונים יש גישה לחברה %s. תוכל להזמין עוד מאוחר יותר.
+ מי הם חבריך לצוות\?
+ אנחנו ניצור עבורם חדרים. אתה יכול להוסיף עוד מאוחר יותר גם.
+ איזה דיונים אתה רוצה לקיים ב-%s\?
+ תן לזה שם כדי להמשיך.
+ הוסף כמה פרטים כדי לשפר לזיהוי. אתה יכול לשנות את זה בכל שלב.
+ הוסף כמה פרטים כדי לבלוט. אתה יכול לשנות את זה בכל שלב.
+ צור מרחב
+ הזמן רק, הכי טוב לעצמך או לצוותים שלך
+ פְּרָטִי
+ פתוח לכל אחד, הכי מתאים לקהילות
+ צִבּוּרִי
+ מרחב פרטי עבורך ועבור חברי הצוות שלך
+ אני וחברי הצוות
+ מרחב פרטי לארגון החדרים שלך
+ רק אני
+ ודא שלאנשים הנכונים יש גישה אל %s.
+ עם מי אתה עובד\?
+ כדי להצטרף למרחב קיים, אתה צריך הזמנה.
+ אתה יכול לשנות את זה מאוחר יותר
+ איזה סוג מרחב אתה רוצה ליצור\?
+ המרחב הפרטי שלך
+ המרחב הציבורי שלך
+ הוסף מרחב
+ מרחב אישי
+ מרחב ציבורי
+ האם אתה בטוח שברצונך למחוק את כל ההודעות שלא נשלחו בחדר הזה\?
+ מחק הודעות שלא נשלחו
+ שליחת ההודעות נכשלה
+ האם ברצונך לבטל את שליחת ההודעה\?
+ מחק את כל ההודעות שנכשלו
+ נִכשָׁל
+ נשלח
+ שְׁלִיחָה
+ משדרג חדר לגרסה חדשה
+ עזוב את החדר עם מזהה נתון (או החדר הנוכחי אם ריק)
+ הצטרף למרחב עם המזהה הנתון
+ הוסף למרחב הנתון
+ צור מרחב
+ תוכן האירוע
+ מצב האירוע נשלח!
+ האירוע נשלח!
+ אירוע שגוי
+ חסר סוג הודעה
+ אין תוכן
+ תוכן האירוע
+ מצב מפתח
+ סוג
+ שלח אירוע מצב מותאם אישית
+ ערוך תוכן
+ מצב אירוע
+ שלח מצב אירוע
+ שלח אירוע מותאם אישית
+ חקור מצב חדר
+ כלי מפתח
+ לא זמין
+ לא על הקו
+ על הקו
+ חדר ציבורי
+ צפה באישורי קריאה
+ אל תתריעה
+ מתריעה ללא קול
+ מתריעה עם צליל
+ ההודעה לא נשלחה עקב שגיאה
+ לא בָּדוּק
+ בָּדוּק
+ הזמינו בדואר אלקטרוני
+ זה רק אתה כרגע. %s יהיה טוב יותר עם אחרים.
+ בחלל זה אין חדרים
+ אנא צור קשר עם מנהל השרת הביתי שלך לקבלת מידע נוסף
+ נראה שהשרת הביתי שלך עדיין לא תומך במרחבים
+ מרגיש ניסיוני\?
+\nניתן להוסיף חללים קיימים למרחב.
+ הצג את כל החדרים בדף הבית
+ כל החדרים שבהם אתה נמצא יוצגו בדף הבית.
+ ניהול חדרים ומרחבים
+ סמן כלא מוצע
+ מוצע
+ סמן כמוצע
+ מחפש מישהו שאינו ב-%s\?
+ %s מזמין אותך
+ הערה: האפליקציה תופעל מחדש
+ אפשר הודעות שרשור
+ המערכת שלך תשלח אוטומטית יומנים כאשר מתרחשת שגיאה ללא יכולת לפענח
+ דווח אוטומטית על שגיאות פענוח.
+ אתם מוזמנים
+ מרחבים הם דרך חדשה לאיחוד של חדרים ואנשים.
+ הוסף מרחב לכל מרחב שאתה מנהל.
+ הוסף מרחבים קיימים
+ הוסף חדרים קיימים
+ הוסף חדרים ומרחבים קיימים
+ בחר דברים להשאיר
+ השאירו חדרים ומרחבים ספציפיים…
+ אל תעזובו חדרים וא מרחבים
+ עזבו את כל החדרים והמרחבים
+ אתה המנהל היחיד של המרחב הזה. עזיבה תגרום לכך שאף אחד לא ישלוט על המרחב.
+ לא תוכל להצטרף מחדש אלא אם כן תוזמן מחדש.
+ אתה האדם היחיד כאן. אם תעזוב, אף אחד לא יוכל להצטרף בעתיד, כולל אותך.
+ האם אתה בטוח שברצונך לעזוב את %s\?
+ עזוב את המרחב
+ הוסיפו חדרים
+ גלה חדרים
+
+ אדם %d שאתה מכיר כבר הצטרף
+ %d אנשים שאתה מכיר כבר הצטרפו
+ %d אנשים שאתה מכיר כבר הצטרפו
+ %d אנשים שאתה מכיר כבר הצטרפו
+
+ גילוי (%s)
+ סיים את ההגדרה
+ הזמן בדואר אלקטרוני, מצא אנשי קשר ועוד…
+ סיים להגדיר את הגילוי.
+ אינך משתמש כעת בשרת זהות. על מנת להזמין חברים לצוות ולהיות ניתנים לגילוי על ידם, הגדר שרת זהות למטה.
+ כינוי זה אינו נגיש בשלב זה.
+\nנסה שוב מאוחר יותר, או בקש ממנהל חדר לבדוק אם יש לך גישה.
+ הם לא יהיו חלק מ-%s
+ רק לחדר הזה
+ הם יוכלו לחקור את %s
+ הזמן אל %s
+ שתף קישור
+ הזמן לפי שם משתמש או דואר אלקטרוני
+ ההצפנה הוגדרה בצורה שגויה.
+ אמת על ידי השוואת אימוג\'י
+ סרוק עם המכשיר הקיים
+ סרוק את הקוד עם המכשיר האחר או החלף וסרוק את הקוד מהמכשיר הקיים
+ קול
+ יצירת מרחב…
+ כתובת מרחב
+ קידומת ( ͡° ͜ʖ ͡°) להודעת טקסט רגילה
+ הראה קצת מידע שימושי לעזור לטיפול בבאגים ביישום
+ הראה מידע על באגים במסך
+ נראה שכתובת הדואר האלקטרוני אינה תקפה
+ התחבר לשרת
+ מחפש להצטרף לשרת קיים \?
+ עדיין לא בטוח \? אתה יכול %s
+ קהילות
+ צוותים
+ חברים ומשפחה
+ נעזור לך להיות מחובר.
+ עם מי תדברו הכי הרבה\?
+ הצפנה קצה לקצה ולא נדרש מספר טלפון. אין פרסומות או כריית מידע.
+ בחירת מקום שמירת השיחה שלך , נותנת לך בקרה ועצמאות . מחובר דרך מטריקס.
+ תקשורת מאובטחת ועצמאית המעניקה לך את אותה רמת פרטיות כמו שיחה פנים אל פנים בבית שלך.
+ הודעות לקבוצתך.
+ אתה בבקרה.
+ שיחות בבעלותך.
+ הגדרות חדר
+ סקר
+ הקובץ גדול מדי להעלאה.
+ האם אתה מאשר את שליחת המידע \?
+ שליחת דואר אלקטרוני ומספרי טלפון אל %s
+ רשימת אנשי הקשר שלך הינה פרטית. לחשיפת משתמשים מרשימת אנשי הקשר שלך , נדרש אישורך לשליחת מידע על איש הקשר לשרת ההזדהות.
+ לא סופקה מדיניות על ידי שרת הזדהות
+ הסתר מדיניות שרת הזדהות
+ הראה מדיניות שרת הזדהות
+ פתח הגדרות
+ משוב על מרחבים
+ הגדרות מערכת
+ גרסאות
+ קבלת עזרה בשימוש ${app_name}
+ עזרה ותמיכה
+ עזרה
+ משפטים
+ אתה צופה בת\'רד זה!
+ יצירת מרחב חדש
+ צפייה בחדר
+ מענה בת\'רד
+ הצגת מידע על המשתמש
+ משנה את האווטר שלך בחדר הנוכחי בלבד
+ משנה את האווטר בחדר הנוכחי
+ משנה את הכינוי בחדר הנוכחי בלבד
+ הפקודה \"%s\" מזוהה אך אינה נתמכת.
+ עזרו לנו לזהות ולשפר את ${app_name} על ידי שיתוף השימוש בצורה אנונימי. להבנת השימוש של אנשים במכשירים שונים , אנחנו נחולל מזהה אקראי , אשר ישותף על ידי המכשירים שלך .
+\n
+\n ניתן לקרוא את כל התנאים %s.
+
+ התוצאה הסופית מתבססת על הצבעה %1$d
+
+ התוצאה הסופית מתבססת על הצבעות %1$d
+
+
+ בחר אילו מרחבים יכולים לגשת לחדר זה. בבחירת מרחב החברים יוכלו למצוא ולהצטרף לחדר.
+ חברים במרחב %s יכולים למצוא , לצפות ולהצטרף.
+ כל אחד במרחב בחדר זה יכול להצטרף. רק מנהלי מערכת של החדר יכולים להוסיף למרחב.
+ אנחנו לא משתפים מידע עם חברות צד שלישי
+ אנחנו לא מקליטים או עושים פרופיל מנתוני החשבון
+ הפסק להתעלם ממשתמש , אשר הודעותיו נראות
+ הגדר את שם החדר
+ התעלם ממשתמש , אשר מעלים הודעות ממך
+ האם מאושרת עזיבת שיחת הועידה הנוכחית ומעבר לשיחת ועידה אחרת \?
+ מצטערים , אירעה שגיאה בניסיון הצטרפות לשיחת הועידה
+ השרת כבר נמצא ברשימה
+ לא ניתן למצוא את השרת או את רשימת החדשים
+ הכנס את שם השרת החדש שיחשף
+ הוספת שרת חדש
+ השרת שלך
+ גרסת חדר
+ מרחבים או חדרים שאינכם מכירים
+ מרחב שמכיל את החדר
+ בחרו מרחבים
+ מרחבים פתוחים
+ אפשרו לחברים במרחב להצטרף.
+ מרחב לחברים בלבד
+ כל אחד יכול למצוא את המרחב ולהצטרף
+ כל אחד יכול להצטרף
+ ציבורי
+ רק מוזמנים יכולים להצטרף
+ פרטי (מוזמן בלבד)
+ פרטי
+ הגדרת גישה לא ידועה(%s)
+ כל אחד יכול לבקש להצטרף לחדר , החברים יוכלו לאשר או לדחות זאת
+ סדר כתובות במרחב זה.
+ מרחב כתובות
+ אפשר לאורחים להצטרף
+ מרחב גישה
+ למי יש גישה\?
+ הגדרות חשבון
+ ניתן לסדר את ההתראות ב-%1$s.
+ שימו לב שהתראות על מילים מוזכרות לא זמינות בחדרים מוצפנים בטלפון הנייד
+ הודע לי עבור
+ אין מדיניות לשרת זה
+ ספריות חברות צד שלישי
+ מדיניות שרת ההזדהות שלך
+ מדיניות השרת הביתי שלך
+ מדיניות ${app_name}
+ ניתן לסגור בכל זמן בהגדרות
+ כאן
+ עזרה בשיפור ${app_name}
+ לא תתקבלנה התראות על מילים המוזכרות בחדרים מוצפנים בטלפון הנייד.
+ הודעות על ידי בוט
+ חדר@
+ הודעות קבוצתיות
+ הודעות ישירות מוצפנות
\ No newline at end of file
diff --git a/vector/src/main/res/values-pt-rBR/strings.xml b/vector/src/main/res/values-pt-rBR/strings.xml
index cd237407d2..f2eaf8d993 100644
--- a/vector/src/main/res/values-pt-rBR/strings.xml
+++ b/vector/src/main/res/values-pt-rBR/strings.xml
@@ -1414,7 +1414,7 @@
Quase lá! %s está mostrando um tick (✓)\?SimNão
- A conexão com o servidor foi perdida
+ Conectividade ao servidor tem sido perdidaModo avião está ligadoFerramentas DevDados de Conta
diff --git a/vector/src/main/res/values-ru/strings.xml b/vector/src/main/res/values-ru/strings.xml
index 465bbbb28c..9a925ecaa7 100644
--- a/vector/src/main/res/values-ru/strings.xml
+++ b/vector/src/main/res/values-ru/strings.xml
@@ -39,7 +39,6 @@
Приглашение в комнату%1$s и %2$sПустая комната
-
Начальная синхронизация:
\nИмпорт учетной записи…Начальная синхронизация:
@@ -258,7 +257,6 @@
УдалитьПереименоватьПожаловаться на содержимое
-
илиПриглашениеВыйти из учётной записи
@@ -281,7 +279,6 @@
Только Matrix контактыНет результатовКомнаты
-
Отправить логиОтправить журналы ошибокОтправить снимок экрана
@@ -309,11 +306,9 @@
Это не похоже на действительный адрес электронной почтыЭтот адрес электронной почты уже используется.Забыли пароль?
-
Этот домашний сервер хочет убедиться, что вы не роботДолжен быть введен адрес электронной почты привязанный к учетной записи.Не удалось проверить адрес электронной почты: убедитесь, что вы перешли по ссылке из сообщения
-
Пожалуйста, введите корректный URLНеверный формат JSONНе содержит допустимого JSON
@@ -329,12 +324,10 @@
Идёт разговор…Вызываемый абонент не смог ответить.Информация
-
${app_name} необходимы разрешения на доступ к микрофону, чтобы выполнять звонки.${app_name} необходимы разрешения на доступ к камере и микрофону для видеовызовов.
\n
\nПожалуйста дайте разрешение в следующем окне для звонка.
-
ДАНЕТПродолжить
@@ -342,7 +335,6 @@
ПрисоединитьсяОтклонитьПерейти к непрочитанному
-
Покинуть комнатуВы уверены, что хотите выйти из комнаты\?ПРЯМЫЕ СООБЩЕНИЯ
@@ -369,7 +361,6 @@
Сертификат был изменен с того, которому доверял ваш телефон. Это ОЧЕНЬ НЕОБЫЧНО. Рекомендуется НЕ ПРИНИМАТЬ этот новый сертификат.Сертификат изменился с ранее доверенного на недействительный. Возможно, сервер обновил свой сертификат. Свяжитесь с администратором сервера для получения ожидаемого отпечатка сертификата.Примите сертификат только если администратор сервера опубликовал отпечаток сертификата, который соответствует указанному выше.
-
ПоискФильтр списка пользователейНет результатов
@@ -414,7 +405,6 @@
Обновить публичное имяНедавно%1$s @ %2$s
-
АутентификацияАвторизован какДомашний сервер
@@ -445,7 +435,6 @@
Это экспериментальные функции, которые могут повести себя неожиданным образом. Используйте с осторожностью.Установить как основной адресСбросить основной адрес
-
Ошибка дешифровкиПубличное имяID сессии
@@ -456,7 +445,6 @@
ЭкспортВведите парольную фразуПодтвердите парольную фразу
-
Импорт E2E ключей комнатыИмпорт ключей комнатыИмпортировать ключи из локального файла
@@ -468,7 +456,6 @@
ПодтвердитьЧтобы убедиться, что этой сессии можно доверять, обратитесь к ее владельцу, используя другие способы (например, лично или по телефону), и спросите, соответствует ли ключ, который он видит в настройках для этой сессии:Если они не совпадают, безопасность вашего общения может быть поставлена под угрозу.
-
Выбор каталога комнатИмя сервераВсе комнаты на сервере %s
@@ -545,7 +532,6 @@
Причина: %1$sВстряхните устройство, чтобы сообщить об ошибкеСписок участников
-
%d комната%d комнаты
@@ -560,7 +546,6 @@
Аватар
-
%d участник%d участника
@@ -573,7 +558,6 @@
%d новых сообщений
-
%d изменение членства%d изменения членства
@@ -586,7 +570,6 @@
%d непрочитанных уведомлений
-
ЧутьеОтправить стикерОтправить стикер
@@ -633,18 +616,12 @@
Нажмите здесь для просмотра старых сообщенийПрисоединиться к комнате с указанным адресомДля исправления управления приложениями Matrix
-
-
-
-
%d выбран%d выбрано%d выбраны
-
-
Системные оповещенияОшибкаСоздать парольную фразу
@@ -733,7 +710,6 @@
Показывать события о вступлении/выходеПоказывать события аккаунтаВключает изменения аватара и отображаемого имени.
-
Использовать системную камеру вместо камеры Element.%1$s: %2$s%d+
@@ -814,7 +790,6 @@
Невозможно расшифровать резервную копию с помощью этого ключа восстановления: убедитесь, что вы ввели правильный ключ.Невозможно расшифровать резервную копию с помощью этого пароля: убедитесь, что вы ввели правильный пароль.Генерация ключей восстановления с использованием парольной фразы может занять несколько секунд.
-
[%1$s]
\nЭта ошибка вне контроля ${app_name}. На телефоне нет учетной записи Google. Пожалуйста, добавьте аккаунт Google.[%1$s]
@@ -855,7 +830,6 @@
Использовать резервное копирование ключейУправление резервным копированием ключейНовые ключи зашифрованных сообщений
-
Ваши ключи копируются.(Дополнительно) Настройка с ключом восстановленияИли защитите резервную копию с помощью ключа восстановления, сохранив его в безопасном месте.
@@ -910,11 +884,8 @@
ПоделитьсяЗапрос поделится ключомИгнорировать
-
Проверено!Понял
-
-
Запрос на подтверждение%s желает подтвердить вашу сессиюНеизвестная ошибка
@@ -1011,7 +982,6 @@
НиктоОтменаОтключить
-
Не удается связаться с домашним сервером по этому URL, пожалуйста, проверьте егоОптимизирован для батареиОптимизирован для работы в реальном времени
@@ -1023,7 +993,6 @@
${app_name} будет синхронизироваться в фоновом режиме периодически в точное время (настраивается).
\nЭто повлияет на использование радио и батареи, появится постоянное уведомление о том, что ${app_name} прислушивается к событиям.Вы не будете уведомлены о входящих сообщениях, когда приложение находится в фоновом режиме.
-
Изменить настройки обнаружения.Вы не используете какой-либо сервер обнаруженияПохоже, вы пытаетесь подключиться к другому домашнему серверу. Вы хотите выйти\?
@@ -1090,7 +1059,7 @@
Покинуть комнату%1$s сделал(а) комнату доступной для всех, у кого есть ссылка.%1$s сделал(а) комнату доступной только по приглашению.
- Подробные логи помогут разработчикам, предоставив больше информации, когда вы отправляете ВзмахЯрости. Даже когда они разрешены, приложение не записывает ваши сообщения и другие приватные данные.
+ Подробные логи помогут разработчикам, предоставив больше информации, когда вы отправляете \"Яростное встряхивание\". Даже когда они разрешены, приложение не записывает ваши сообщения и другие приватные данные.Закройте меню создание комнаты…ВнизКонтакт
@@ -1276,7 +1245,6 @@
Лента сообщенийКлюч сообщенияРаспечатайте его и храните в безопасном месте
-
Шифрование включеноШифрование не включено%1$s: %2$s
@@ -1311,7 +1279,6 @@
Закрыть окно резервного копирования ключей%s прочитаноНе удалось обработать данные
-
ВоспроизвестиКопироватьУдачно
@@ -1405,10 +1372,10 @@
Это недопустимый идентификатор пользователя. Ожидаемый формат: \'@user:homeserver.org\'Не удалось найти действительный домашний сервер. Пожалуйста, проверьте свой идентификаторНачальная синхронизация…
- СотрясениеЯрости
+ Яростное встряхиваниеПорог обнаруженияВстряхните телефон, чтобы проверить порог обнаружения
- Обнаружено потрясение!
+ Обнаружено встряхивание!Показываем только первые результаты, наберите больше букв…Раннее падение${app_name} может падать чаще, когда происходит непредвиденная ошибка
@@ -1443,7 +1410,6 @@
Подтверждено %sПодтверждённых %sОжидаем %s…
-
Сообщения в этой комнате не защищены сквозным шифрованием.Сообщения в этой комнате защищены сквозным шифрованием.
\n
@@ -1871,7 +1837,6 @@
Скрыть дополнительные настройкиПоказать дополнительные настройки%1$d из %2$d
-
Дать согласиеОтозвать моё согласиеБольше никаких результатов
@@ -1973,8 +1938,6 @@
ПереводПодключитьсяСначала посоветуйтесь
-
-
Нет учётных данных, неправильная учётная запись пользователя и/или парольВы уверены, что хотите удалить все неотправленные сообщения в этой комнате\?Удалить неотправленные сообщения
@@ -2061,7 +2024,6 @@
ОбновлениеПожалуйста, будьте терпеливы, это может занять некоторое время.Присоединиться к замещенной комнате
-
Безымянная КомнатаНекоторые комнаты могут быть скрыты, потому что они приватные, и вам нужно приглашение.Некоторые комнаты могут быть скрыты, потому что они приватные, и вам нужно приглашение.
@@ -2130,7 +2092,7 @@
Приватное пространство для организации ваших комнатЯ и члены командыТолько я
- Убедитесь, что нужные люди имеют доступ к %s. Вы сможете изменить это позже.
+ Убедитесь, что нужные люди имеют доступ к %s.С кем вы работаете\?Чтобы присоединиться к существующему пространству, вам необходимо получить приглашение.Вы сможете изменить это позже
@@ -2453,7 +2415,6 @@
МестоположениеВы согласны отправить эту информацию\?Чтобы обнаружить существующие контакты, необходимо отправить контактную информацию (электронную почту и номера телефонов) на сервер обнаружения. Мы хешируем ваши данные перед отправкой для обеспечения конфиденциальности.
-
Отправить электронные адреса и номера телефонов %sВаши контакты приватны. Чтобы обнаружить пользователей из ваших контактов, нам необходимо ваше разрешение на отправку контактной информации на ваш сервер обнаружения.Системные настройки
@@ -2485,16 +2446,16 @@
ВключитьСлежка за уведомлениямиВам не разрешено подключаться к этой комнате
- Организуйте обсуждение в потоках
- Показать все потоки в которых вы участвуете
- Все Потоки
- Просмотр Потоков
+ Организуйте обсуждение с помощью веток
+ Показать все ветки, в которых вы участвуете
+ Все ветки
+ Посмотреть веткиПосмотреть в комнате
- Показать всплывающие сообщения
+ Показывать сообщения в пузыряхНе удалось загрузить картуКартаПримечание: приложение будет перезапущено
- Включить Сообщения Потока
+ Включить ветки сообщенийПодключиться к серверуХотите присоединиться к существующему серверу\?пропустить вопрос
@@ -2504,18 +2465,36 @@
Друзья и семьяМы поможем вам подключится.С кем вы будете общаться больше всего\?
- Вы уже просматриваете этот Поток!
+ Вы уже просматриваете эту ветку!Просмотр в Комнате
- Ответить в Поток
- Команда «%s» распознается, но не поддерживается в потоках.
- Из Потока
+ Ответить в ветке
+ Команда «%s» распознается, но не поддерживается в ветках.
+ Из веткиСовет: нажмите и удерживайте сообщение и используйте «%s».
- Потоки помогают хранить ваши разговоры по темам и легко отслеживать их.
- Мои Потоки
- Показать все потоки в текущей комнате
+ Ветки помогают хранить ваши разговоры по темам и легко отслеживать их.
+ Мои ветки
+ Показать все ветки этой комнатыФильтр
- Потоки
- Поток
- Фильтровать Потоки в комнате
- Скопировать ссылку в поток
+ Ветки
+ Ветка
+ Фильтровать ветки в комнате
+ Скопировать ссылку в ветку
+ Уведомления комнаты
+ Пользователи
+ Оповестить всю комнату
+
+ И ещё %1$d
+ И ещё %1$d
+ И ещё %1$d
+ И ещё %1$d
+
+ Свернуть
+ %1$s, %2$s и другие
+ %1$s и %2$s
+
+ %d изменение ACL сервера
+ %d изменения ACL сервера
+ %d изменений ACL сервера
+ %d изменений ACL сервера
+
\ No newline at end of file
diff --git a/vector/src/main/res/values-sk/strings.xml b/vector/src/main/res/values-sk/strings.xml
index 8d97ff7266..6650890ac3 100644
--- a/vector/src/main/res/values-sk/strings.xml
+++ b/vector/src/main/res/values-sk/strings.xml
@@ -2274,7 +2274,7 @@
Týmto sa zastaví možnosť hlasovania a zobrazia sa konečné výsledky ankety.Určite chcete túto anketu odstrániť\? Po odstránení ju už nebudete môcť obnoviť.Typ ankety
- Otvoriť anketu
+ Otvorená anketaHlasujúci uvidia výsledky hneď po hlasovaníUzavretá anketaZobraziť vlákna
@@ -2452,4 +2452,18 @@
%1$d ďalšíchZadajte URL adresu servera Modular Element alebo adresu servera, ktorý si želáte použiť
+ Hlasovať
+ Odoslať stav udalosti
+ Priradenie sa nepodarilo.
+ V súčasnosti neexistuje žiadne priradenie k tomuto identifikátoru.
+ použite záložný kľúč na obnovu kľúča
+ Uloženie tajnej zálohy kľúčov v SSSS
+ Generovanie kľúča SSSS z kľúča pre obnovu
+ Definovanie predvoleného kľúča SSSS
+ Rýchle-zlyhanie
+ Najprv konzultovať
+ Vyberte si, čo opustíte
+ Opustiť miestnosť s daným id (alebo aktuálnu miestnosť, ak je prázdna)
+ Varovná úroveň dôveryhodnosti
+ Pripojiť
\ No newline at end of file
diff --git a/vector/src/main/res/values-sq/strings.xml b/vector/src/main/res/values-sq/strings.xml
index 48fc274eb7..0fc5c7f6fb 100644
--- a/vector/src/main/res/values-sq/strings.xml
+++ b/vector/src/main/res/values-sq/strings.xml
@@ -310,7 +310,7 @@
POVazhdoHiqe
- Bëhuni pjesë
+ HyniHidheni tejAnëtarë listeHidhu te të palexuarit
diff --git a/vector/src/main/res/values-zh-rCN/strings.xml b/vector/src/main/res/values-zh-rCN/strings.xml
index d2e17e856d..67bf3f5e06 100644
--- a/vector/src/main/res/values-zh-rCN/strings.xml
+++ b/vector/src/main/res/values-zh-rCN/strings.xml
@@ -39,7 +39,6 @@
空聊天室聊天室邀请%1$s 和 %2$s
-
初始化同步:
\n正在导入账号…初始化同步:
@@ -262,10 +261,8 @@
拍摄照片或视频此主服务器想确认你不是机器人电子邮箱地址验证失败:请确保你已点击邮件中的链接
-
原始通话正在连接…
-
${app_name} 需要权限以访问你的麦克风来进行语音通话。私聊邀请
@@ -283,7 +280,6 @@
忽略指纹(%s):无法验证远程服务器的身份。
-
应用信息启用这个账号的通知启用这个设备的通知
@@ -301,7 +297,6 @@
通知已忽略的用户通讯录权限
-
身份认证当前密码是否重新显示所有来自 %s 的消息?
@@ -319,14 +314,12 @@
高级此聊天室的内部 ID这些是实验性功能,可能会出现不可预料的错误。请谨慎使用。
-
导出端对端聊天室密钥导出聊天室密钥导出密钥到本地文件导出输入密语确认密语
-
导入端对端聊天室密钥导入聊天室密钥从本地文件导入密钥
@@ -338,25 +331,20 @@
永久链接重命名举报内容
-
问题反馈为分析此问题,本客户端的日志将会随此问题反馈发送。本问题反馈,包括日志与截图,将不会被公开显示。若你希望仅发送上面的文字,请取消选择:问题反馈发送成功问题反馈发送失败(%s)
-
异常的 JSON呼入的视频通话呼入的语音通话通话中…通话未被接听。信息
-
-
${app_name} 需要权限以访问你的摄像机和麦克风来进行视频通话。
\n
\n请在接下来的弹出窗口中授权允许访问,以便进行通话。移除
-
你将不能撤销这个修改,因为你正在让这个用户和你拥有相同的特权级别。
\n你确定吗?这可能意味着有人正在恶意劫持你的流量,或者你的手机不信任远程服务器提供的数字证书。
@@ -375,7 +363,6 @@
取消设置为主要地址确认你似乎沮丧地摇了摇手机。你想打开问题反馈界面吗?
-
证书已从一个先前受你的设备信任的证书更改为另一个。这非常反常!建议你不要接受此新证书。证书已从曾受信任的证书更改为不受信任的证书。服务器可能已更新其证书,请联系管理员并核对服务器的指纹。请仅在服务器管理员发布了与上述指纹匹配的指纹的情况下接受该证书。
@@ -391,7 +378,6 @@
实验室为验证此设备是否可信,请通过其他方式(例如面对面交换或拨打电话)与其拥有者联系,并询问他们该设备的用户设置中的密钥是否与以下密钥匹配:如果它们不匹配,你通讯的安全性可能会受到影响。
-
邀请收藏夹联系人
@@ -479,7 +465,6 @@
社群摇一摇快捷反馈问题
-
%d 位成员的状态发生了变化
@@ -490,7 +475,6 @@
%d 条未读消息显示成员
-
徽章%d 个聊天室
@@ -505,9 +489,7 @@
你已被 %2$s 从 %1$s 中封禁理由:%1$s头像
-
%1$s 条在 %2$s 中
-
停用账号停用我的账号发送统计分析数据
@@ -553,16 +535,9 @@
对话在此继续这个聊天室是另一个对话的延续点击此处查看更早的消息
-
-
-
-
-
已选择 %d 个
-
-
系统警告联系你的服务管理员本服务器其中一项资源已超出限制,部分用户将无法登录。
@@ -631,7 +606,6 @@
邀请、移除与封禁事件不受影响。显示账号变动事件包括头像与显示名称的变动。
-
密码%d+%1$s:%2$s
@@ -719,7 +693,6 @@
保存恢复密钥分享保存为文件
-
请制作一份拷贝分享恢复密钥…正在使用密语来生成恢复密钥,此过程可能会花费几秒钟。
@@ -765,7 +738,6 @@
正在删除备份…删除备份要从此服务器中删除你备份的加密密钥吗?你将无法再使用恢复密钥来读取加密的历史消息。
-
永不丢失已加密消息使用备份密钥新加密信息密钥
@@ -783,7 +755,6 @@
按回车发送消息软键盘的 Enter 按钮将发送消息而不是添加换行符密码无效
-
媒体默认压缩选择
@@ -865,7 +836,6 @@
撤消断开连接拒绝
-
這不是有效的 Matrix 服务器位置无法在此 URL 找到主服务器,请检查播放
@@ -918,7 +888,6 @@
\n这将影响网络和电池的使用,将显示一个永久通知表明 ${app_name} 正在监听事件。无后台同步应用在后台时你不会收到消息通知。
-
集成使用集成管理器管理机器人、桥接、部件和贴纸包。
\n集成管理器接收配置数据,可以代表你修改部件、发送聊天室邀请及设置特权等级。
@@ -972,8 +941,6 @@
安全备份保护加密信息及数据的访问权设置安全备份
-
-
你未使用身份服务器你似乎正在试图连接到另一个主服务器。你想要登出吗?你已经跟上了!
@@ -1096,7 +1063,6 @@
此内容已报告为不合适。
\n
\n如果你不希望再看到此用户的更多内容,你可以忽略他们以隐藏他们的消息。
-
忽略用户全部消息(嘈杂)全部消息
@@ -1295,7 +1261,6 @@
验证 %s已验证 %s正在等待 %s…
-
此聊天室的消息未经端对端加密。该聊天室的消息已被端对端加密。
\n
@@ -1446,7 +1411,6 @@
密钥已是最新!保存到优盘或者备份盘复制到你的个人云存储
-
如果你现在取消,那么当你失去登录权限时也会丢失加密的信息和数据。
\n
\n你也可以通过设置菜单来建立保护备份以及管理你的密钥。
@@ -1754,7 +1718,6 @@
%2$d 的 %1$d旋转和裁剪添加图像自
-
授予许可撤销我的许可你已同意发送电子邮件和电话号码到身份服务器以从你的联系人发现其他用户。
@@ -1823,7 +1786,6 @@
已勾选已选中活跃通话(%1$s)
-
需要重新验证删除失败的消息你确定要取消发送消息吗?
@@ -1987,7 +1949,6 @@
${app_name} 要求你输入凭据才能执行此操作。呼叫转移时发生错误先询问
-
查找电话号码时发生了错误此通话已结束%1$s 拒绝了此通话
@@ -2075,7 +2036,6 @@
输入你想要探索的新服务器的名称。添加一个新的服务器你的服务器
-
抱歉,尝试加入 %s 时发生了一个错误空间地址查看和管理这个空间的地址。
@@ -2272,7 +2232,6 @@
投票问题或主题创建投票投票
-
向 %s 发送电子邮件和电话号码您的联系人是私密的。 要从您的联系人中发现用户,我们需要您的许可才能将联系信息发送到您的身份服务器。已退出此会话!
@@ -2321,4 +2280,8 @@
\n你可以阅读我们所有的条款 %s。帮助改进 ${app_name}启用
+ 不允许加入此房间
+
+ 修改服务器 %d 的 ACLs
+
\ No newline at end of file
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 9a30e89948..a276e07b1e 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -731,6 +731,8 @@
Tip: Long tap a message and use “%s”.From a Thread
+ Threads Approaching Beta 🎉
+ We’re getting closer to releasing a public Beta for Threads.\n\nAs we prepare for it, we need to make some changes: threads created before this point will be displayed as regular replies.\n\nThis will be a one-off transition as Threads are now part of the Matrix specification.Search
@@ -2946,6 +2948,8 @@
Once enabled you will be able to send your location to any roomRender user locations in the timelineFailed to load map
+ Live location enabled
+ Stop${app_name} Live LocationLocation sharing is in progress
diff --git a/vector/src/main/res/xml/vector_settings_labs.xml b/vector/src/main/res/xml/vector_settings_labs.xml
index 73193edfd5..5144f6fe1f 100644
--- a/vector/src/main/res/xml/vector_settings_labs.xml
+++ b/vector/src/main/res/xml/vector_settings_labs.xml
@@ -52,8 +52,8 @@
diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt
index b17c1a8bba..543d517db1 100644
--- a/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt
+++ b/vector/src/test/java/im/vector/app/features/analytics/impl/DefaultVectorAnalyticsTest.kt
@@ -30,7 +30,7 @@ import im.vector.app.test.fixtures.aVectorAnalyticsScreen
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -60,35 +60,35 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `when setting user consent then updates analytics store`() = runBlockingTest {
+ fun `when setting user consent then updates analytics store`() = runTest {
defaultVectorAnalytics.setUserConsent(true)
fakeAnalyticsStore.verifyConsentUpdated(updatedValue = true)
}
@Test
- fun `when consenting to analytics then updates posthog opt out to false`() = runBlockingTest {
+ fun `when consenting to analytics then updates posthog opt out to false`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = true)
fakePostHog.verifyOptOutStatus(optedOut = false)
}
@Test
- fun `when revoking consent to analytics then updates posthog opt out to true`() = runBlockingTest {
+ fun `when revoking consent to analytics then updates posthog opt out to true`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = false)
fakePostHog.verifyOptOutStatus(optedOut = true)
}
@Test
- fun `when setting the analytics id then updates analytics store`() = runBlockingTest {
+ fun `when setting the analytics id then updates analytics store`() = runTest {
defaultVectorAnalytics.setAnalyticsId(AN_ANALYTICS_ID)
fakeAnalyticsStore.verifyAnalyticsIdUpdated(updatedValue = AN_ANALYTICS_ID)
}
@Test
- fun `given lateinit user properties when valid analytics id updates then identify with lateinit properties`() = runBlockingTest {
+ fun `given lateinit user properties when valid analytics id updates then identify with lateinit properties`() = runTest {
fakeLateInitUserPropertiesFactory.givenCreatesProperties(A_LATE_INIT_USER_PROPERTIES)
fakeAnalyticsStore.givenAnalyticsId(AN_ANALYTICS_ID)
@@ -97,7 +97,7 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `when signing out then resets posthog`() = runBlockingTest {
+ fun `when signing out then resets posthog`() = runTest {
fakeAnalyticsStore.allowSettingAnalyticsIdToCallBackingFlow()
defaultVectorAnalytics.onSignOut()
@@ -106,7 +106,7 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `given user consent when tracking screen events then submits to posthog`() = runBlockingTest {
+ fun `given user consent when tracking screen events then submits to posthog`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = true)
defaultVectorAnalytics.screen(A_SCREEN_EVENT)
@@ -115,7 +115,7 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `given user has not consented when tracking screen events then does not track`() = runBlockingTest {
+ fun `given user has not consented when tracking screen events then does not track`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = false)
defaultVectorAnalytics.screen(A_SCREEN_EVENT)
@@ -124,7 +124,7 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `given user consent when tracking events then submits to posthog`() = runBlockingTest {
+ fun `given user consent when tracking events then submits to posthog`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = true)
defaultVectorAnalytics.capture(AN_EVENT)
@@ -133,7 +133,7 @@ class DefaultVectorAnalyticsTest {
}
@Test
- fun `given user has not consented when tracking events then does not track`() = runBlockingTest {
+ fun `given user has not consented when tracking events then does not track`() = runTest {
fakeAnalyticsStore.givenUserContent(consent = false)
defaultVectorAnalytics.capture(AN_EVENT)
diff --git a/vector/src/test/java/im/vector/app/features/analytics/impl/LateInitUserPropertiesFactoryTest.kt b/vector/src/test/java/im/vector/app/features/analytics/impl/LateInitUserPropertiesFactoryTest.kt
index c2fa50f789..2068099ab9 100644
--- a/vector/src/test/java/im/vector/app/features/analytics/impl/LateInitUserPropertiesFactoryTest.kt
+++ b/vector/src/test/java/im/vector/app/features/analytics/impl/LateInitUserPropertiesFactoryTest.kt
@@ -23,7 +23,7 @@ import im.vector.app.test.fakes.FakeContext
import im.vector.app.test.fakes.FakeSession
import im.vector.app.test.fakes.FakeVectorStore
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
@@ -43,14 +43,14 @@ class LateInitUserPropertiesFactoryTest {
)
@Test
- fun `given no active session when creating properties then returns null`() = runBlockingTest {
+ fun `given no active session when creating properties then returns null`() = runTest {
val result = lateInitUserProperties.createUserProperties()
result shouldBeEqualTo null
}
@Test
- fun `given no use case set on an active session when creating properties then returns null`() = runBlockingTest {
+ fun `given no use case set on an active session when creating properties then returns null`() = runTest {
fakeVectorStore.givenUseCase(null)
fakeSession.givenVectorStore(fakeVectorStore.instance)
fakeActiveSessionDataSource.setActiveSession(fakeSession)
@@ -61,7 +61,7 @@ class LateInitUserPropertiesFactoryTest {
}
@Test
- fun `given use case set on an active session when creating properties then includes the use case`() = runBlockingTest {
+ fun `given use case set on an active session when creating properties then includes the use case`() = runTest {
fakeVectorStore.givenUseCase(FtueUseCase.TEAMS)
fakeActiveSessionDataSource.setActiveSession(fakeSession)
val result = lateInitUserProperties.createUserProperties()
diff --git a/vector/src/test/java/im/vector/app/features/crypto/keys/KeysExporterTest.kt b/vector/src/test/java/im/vector/app/features/crypto/keys/KeysExporterTest.kt
index 57ad2a52ab..5d0317592d 100644
--- a/vector/src/test/java/im/vector/app/features/crypto/keys/KeysExporterTest.kt
+++ b/vector/src/test/java/im/vector/app/features/crypto/keys/KeysExporterTest.kt
@@ -26,7 +26,7 @@ import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
import org.amshove.kluent.internal.assertFailsWith
import org.junit.Before
import org.junit.Test
@@ -55,7 +55,7 @@ class KeysExporterTest {
givenFileDescriptorWithSize(size = A_ROOM_KEYS_EXPORT.size.toLong())
val outputStream = context.givenOutputStreamFor(A_URI)
- runBlocking { keysExporter.export(A_PASSWORD, A_URI) }
+ runTest { keysExporter.export(A_PASSWORD, A_URI) }
verify { outputStream.write(A_ROOM_KEYS_EXPORT) }
}
@@ -66,7 +66,7 @@ class KeysExporterTest {
context.givenOutputStreamFor(A_URI)
assertFailsWith {
- runBlocking { keysExporter.export(A_PASSWORD, A_URI) }
+ runTest { keysExporter.export(A_PASSWORD, A_URI) }
}
}
@@ -75,7 +75,7 @@ class KeysExporterTest {
context.givenMissingOutputStreamFor(A_URI)
assertFailsWith(message = "Unable to open file for writing") {
- runBlocking { keysExporter.export(A_PASSWORD, A_URI) }
+ runTest { keysExporter.export(A_PASSWORD, A_URI) }
}
}
@@ -85,7 +85,7 @@ class KeysExporterTest {
context.givenOutputStreamFor(A_URI)
assertFailsWith(message = "Exported file not found") {
- runBlocking { keysExporter.export(A_PASSWORD, A_URI) }
+ runTest { keysExporter.export(A_PASSWORD, A_URI) }
}
}
diff --git a/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt b/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt
index fc4197e07a..7562dfdf14 100644
--- a/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt
+++ b/vector/src/test/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModelTest.kt
@@ -21,7 +21,7 @@ import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.test.fakes.FakeSession
import im.vector.app.test.fakes.FakeStringProvider
import im.vector.app.test.test
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
@@ -47,117 +47,105 @@ class SharedSecureStorageViewModelTest {
val args = SharedSecureStorageActivity.Args(keyId = null, emptyList(), "alias")
@Test
- fun `given a key info with passphrase when initialising then step is EnterPassphrase`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITH_PASSPHRASE)
- val viewModel = createViewModel()
- viewModel
- .test(this)
- .assertState(aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterPassphrase
- ))
- .finish()
- }
+ fun `given a key info with passphrase when initialising then step is EnterPassphrase`() = runTest {
+ givenKey(KEY_INFO_WITH_PASSPHRASE)
+ val viewModel = createViewModel()
+ viewModel
+ .test()
+ .assertState(aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterPassphrase
+ ))
+ .finish()
}
@Test
- fun `given a key info without passphrase when initialising then step is EnterKey`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
+ fun `given a key info without passphrase when initialising then step is EnterKey`() = runTest {
+ givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
- val viewModel = createViewModel()
+ val viewModel = createViewModel()
- viewModel
- .test(this)
- .assertState(aViewState(
- hasPassphrase = false,
- step = SharedSecureStorageViewState.Step.EnterKey
- ))
- .finish()
- }
+ viewModel
+ .test()
+ .assertState(aViewState(
+ hasPassphrase = false,
+ step = SharedSecureStorageViewState.Step.EnterKey
+ ))
+ .finish()
}
@Test
- fun `given on EnterKey step when going back then dismisses`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
+ fun `given on EnterKey step when going back then dismisses`() = runTest {
+ givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
- val viewModel = createViewModel()
- val test = viewModel.test(this)
- viewModel.handle(SharedSecureStorageAction.Back)
- test
- .assertEvents(SharedSecureStorageViewEvent.Dismiss)
- .finish()
- }
+ val viewModel = createViewModel()
+ val test = viewModel.test()
+ viewModel.handle(SharedSecureStorageAction.Back)
+ test
+ .assertEvents(SharedSecureStorageViewEvent.Dismiss)
+ .finish()
}
@Test
- fun `given on passphrase step when using key then step is EnterKey`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITH_PASSPHRASE)
- val viewModel = createViewModel()
- val test = viewModel.test(this)
+ fun `given on passphrase step when using key then step is EnterKey`() = runTest {
+ givenKey(KEY_INFO_WITH_PASSPHRASE)
+ val viewModel = createViewModel()
+ val test = viewModel.test()
- viewModel.handle(SharedSecureStorageAction.UseKey)
+ viewModel.handle(SharedSecureStorageAction.UseKey)
- test
- .assertStates(
- aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterPassphrase
- ),
- aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterKey
- )
- )
- .finish()
- }
+ test
+ .assertStates(
+ aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterPassphrase
+ ),
+ aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterKey
+ )
+ )
+ .finish()
}
@Test
- fun `given a key info with passphrase and on EnterKey step when going back then step is EnterPassphrase`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITH_PASSPHRASE)
- val viewModel = createViewModel()
- val test = viewModel.test(this)
+ fun `given a key info with passphrase and on EnterKey step when going back then step is EnterPassphrase`() = runTest {
+ givenKey(KEY_INFO_WITH_PASSPHRASE)
+ val viewModel = createViewModel()
+ val test = viewModel.test()
- viewModel.handle(SharedSecureStorageAction.UseKey)
- viewModel.handle(SharedSecureStorageAction.Back)
+ viewModel.handle(SharedSecureStorageAction.UseKey)
+ viewModel.handle(SharedSecureStorageAction.Back)
- test
- .assertStates(
- aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterPassphrase
- ),
- aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterKey
- ),
- aViewState(
- hasPassphrase = true,
- step = SharedSecureStorageViewState.Step.EnterPassphrase
- )
- )
- .finish()
- }
+ test
+ .assertStates(
+ aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterPassphrase
+ ),
+ aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterKey
+ ),
+ aViewState(
+ hasPassphrase = true,
+ step = SharedSecureStorageViewState.Step.EnterPassphrase
+ )
+ )
+ .finish()
}
@Test
- fun `given on passphrase step when going back then dismisses`() {
- runBlockingTest {
- givenKey(KEY_INFO_WITH_PASSPHRASE)
- val viewModel = createViewModel()
- val test = viewModel.test(this)
+ fun `given on passphrase step when going back then dismisses`() = runTest {
+ givenKey(KEY_INFO_WITH_PASSPHRASE)
+ val viewModel = createViewModel()
+ val test = viewModel.test()
- viewModel.handle(SharedSecureStorageAction.Back)
+ viewModel.handle(SharedSecureStorageAction.Back)
- test
- .assertEvents(SharedSecureStorageViewEvent.Dismiss)
- .finish()
- }
+ test
+ .assertEvents(SharedSecureStorageViewEvent.Dismiss)
+ .finish()
}
private fun createViewModel(): SharedSecureStorageViewModel {
diff --git a/vector/src/test/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCaseTest.kt
index 015a27b0c8..7a80cbe87e 100644
--- a/vector/src/test/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCaseTest.kt
@@ -21,7 +21,7 @@ import im.vector.app.features.location.LocationData
import im.vector.app.test.fakes.FakeSession
import io.mockk.MockKAnnotations
import io.mockk.impl.annotations.OverrideMockKs
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -42,7 +42,7 @@ class CompareLocationsUseCaseTest {
}
@Test
- fun `given 2 very near locations when calling execute then these locations are considered as equal`() = runBlockingTest {
+ fun `given 2 very near locations when calling execute then these locations are considered as equal`() = runTest {
// Given
val location1 = LocationData(
latitude = 48.858269,
@@ -62,7 +62,7 @@ class CompareLocationsUseCaseTest {
}
@Test
- fun `given 2 far away locations when calling execute then these locations are considered as not equal`() = runBlockingTest {
+ fun `given 2 far away locations when calling execute then these locations are considered as not equal`() = runTest {
// Given
val location1 = LocationData(
latitude = 48.858269,
diff --git a/vector/src/test/java/im/vector/app/features/media/domain/usecase/DownloadMediaUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/media/domain/usecase/DownloadMediaUseCaseTest.kt
index 2fa8c7d5f7..bb05357cb2 100644
--- a/vector/src/test/java/im/vector/app/features/media/domain/usecase/DownloadMediaUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/features/media/domain/usecase/DownloadMediaUseCaseTest.kt
@@ -38,7 +38,7 @@ import io.mockk.runs
import io.mockk.unmockkStatic
import io.mockk.verify
import io.mockk.verifyAll
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -77,7 +77,7 @@ class DownloadMediaUseCaseTest {
}
@Test
- fun `given a file when calling execute then save the file in local with success`() = runBlockingTest {
+ fun `given a file when calling execute then save the file in local with success`() = runTest {
// Given
val uri = mockk()
val mimeType = "mimeType"
@@ -105,7 +105,7 @@ class DownloadMediaUseCaseTest {
}
@Test
- fun `given a file when calling execute then save the file in local with error`() = runBlockingTest {
+ fun `given a file when calling execute then save the file in local with error`() = runTest {
// Given
val uri = mockk()
val mimeType = "mimeType"
diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
index 085e1a8049..4fd079611d 100644
--- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
+++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt
@@ -23,12 +23,14 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.features.login.ReAuthHelper
+import im.vector.app.features.login.SignMode
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeAnalyticsTracker
import im.vector.app.test.fakes.FakeAuthenticationService
import im.vector.app.test.fakes.FakeContext
import im.vector.app.test.fakes.FakeHomeServerConnectionConfigFactory
import im.vector.app.test.fakes.FakeHomeServerHistoryService
+import im.vector.app.test.fakes.FakeRegisterActionHandler
import im.vector.app.test.fakes.FakeRegistrationWizard
import im.vector.app.test.fakes.FakeSession
import im.vector.app.test.fakes.FakeStringProvider
@@ -36,20 +38,27 @@ import im.vector.app.test.fakes.FakeUri
import im.vector.app.test.fakes.FakeUriFilenameResolver
import im.vector.app.test.fakes.FakeVectorFeatures
import im.vector.app.test.fakes.FakeVectorOverrides
+import im.vector.app.test.fixtures.aHomeServerCapabilities
import im.vector.app.test.test
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
+import org.matrix.android.sdk.api.auth.registration.FlowResult
+import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.auth.registration.Stage
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
private const val A_DISPLAY_NAME = "a display name"
private const val A_PICTURE_FILENAME = "a-picture.png"
private val AN_ERROR = RuntimeException("an error!")
-private val AN_UNSUPPORTED_PERSONALISATION_STATE = PersonalizationState(
- supportsChangingDisplayName = false,
- supportsChangingProfilePicture = false
-)
+private val A_LOADABLE_REGISTER_ACTION = RegisterAction.StartRegistration
+private val A_NON_LOADABLE_REGISTER_ACTION = RegisterAction.CheckIfEmailHasBeenValidated(delayMillis = -1L)
+private val A_RESULT_IGNORED_REGISTER_ACTION = RegisterAction.AddThreePid(RegisterThreePid.Email("an email"))
+private val A_HOMESERVER_CAPABILITIES = aHomeServerCapabilities(canChangeDisplayName = true, canChangeAvatar = true)
+private val AN_IGNORED_FLOW_RESULT = FlowResult(missingStages = emptyList(), completedStages = emptyList())
+private val ANY_CONTINUING_REGISTRATION_RESULT = RegistrationResult.FlowResponse(AN_IGNORED_FLOW_RESULT)
class OnboardingViewModelTest {
@@ -63,6 +72,7 @@ class OnboardingViewModelTest {
private val fakeUriFilenameResolver = FakeUriFilenameResolver()
private val fakeActiveSessionHolder = FakeActiveSessionHolder(fakeSession)
private val fakeAuthenticationService = FakeAuthenticationService()
+ private val fakeRegisterActionHandler = FakeRegisterActionHandler()
lateinit var viewModel: OnboardingViewModel
@@ -72,8 +82,8 @@ class OnboardingViewModelTest {
}
@Test
- fun `when handling PostViewEvent then emits contents as view event`() = runBlockingTest {
- val test = viewModel.test(this)
+ fun `when handling PostViewEvent, then emits contents as view event`() = runTest {
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome))
@@ -83,10 +93,10 @@ class OnboardingViewModelTest {
}
@Test
- fun `given supports changing display name when handling PersonalizeProfile then emits contents choose display name`() = runBlockingTest {
+ fun `given supports changing display name, when handling PersonalizeProfile, then emits contents choose display name`() = runTest {
val initialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingDisplayName = true, supportsChangingProfilePicture = false))
viewModel = createViewModel(initialState)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.PersonalizeProfile)
@@ -96,10 +106,10 @@ class OnboardingViewModelTest {
}
@Test
- fun `given only supports changing profile picture when handling PersonalizeProfile then emits contents choose profile picture`() = runBlockingTest {
+ fun `given only supports changing profile picture, when handling PersonalizeProfile, then emits contents choose profile picture`() = runTest {
val initialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingDisplayName = false, supportsChangingProfilePicture = true))
viewModel = createViewModel(initialState)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.PersonalizeProfile)
@@ -109,82 +119,157 @@ class OnboardingViewModelTest {
}
@Test
- fun `given homeserver does not support personalisation when registering account then updates state and emits account created event`() = runBlockingTest {
- fakeSession.fakeHomeServerCapabilitiesService.givenCapabilities(HomeServerCapabilities(canChangeDisplayName = false, canChangeAvatar = false))
- givenSuccessfullyCreatesAccount()
- val test = viewModel.test(this)
+ fun `when handling SignUp then sets sign mode to sign up and starts registration`() = runTest {
+ givenRegistrationResultFor(RegisterAction.StartRegistration, ANY_CONTINUING_REGISTRATION_RESULT)
+ val test = viewModel.test()
- viewModel.handle(OnboardingAction.RegisterDummy)
+ viewModel.handle(OnboardingAction.UpdateSignMode(SignMode.SignUp))
test
- .assertStates(
+ .assertStatesChanges(
initialState,
- initialState.copy(asyncRegistration = Loading()),
- initialState.copy(
- asyncLoginAction = Success(Unit),
- asyncRegistration = Loading(),
- personalizationState = AN_UNSUPPORTED_PERSONALISATION_STATE
- ),
- initialState.copy(
- asyncLoginAction = Success(Unit),
- asyncRegistration = Uninitialized,
- personalizationState = AN_UNSUPPORTED_PERSONALISATION_STATE
- )
+ { copy(signMode = SignMode.SignUp) },
+ { copy(asyncRegistration = Loading()) },
+ { copy(asyncRegistration = Uninitialized) }
+ )
+ .assertEvents(OnboardingViewEvents.RegistrationFlowResult(ANY_CONTINUING_REGISTRATION_RESULT.flowResult, isRegistrationStarted = true))
+ .finish()
+ }
+
+ @Test
+ fun `given register action requires more steps, when handling action, then posts next steps`() = runTest {
+ val test = viewModel.test()
+ givenRegistrationResultFor(A_LOADABLE_REGISTER_ACTION, ANY_CONTINUING_REGISTRATION_RESULT)
+
+ viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
+
+ test
+ .assertStatesChanges(
+ initialState,
+ { copy(asyncRegistration = Loading()) },
+ { copy(asyncRegistration = Uninitialized) }
+ )
+ .assertEvents(OnboardingViewEvents.RegistrationFlowResult(ANY_CONTINUING_REGISTRATION_RESULT.flowResult, isRegistrationStarted = true))
+ .finish()
+ }
+
+ @Test
+ fun `given register action is non loadable, when handling action, then posts next steps without loading`() = runTest {
+ val test = viewModel.test()
+ givenRegistrationResultFor(A_NON_LOADABLE_REGISTER_ACTION, ANY_CONTINUING_REGISTRATION_RESULT)
+
+ viewModel.handle(OnboardingAction.PostRegisterAction(A_NON_LOADABLE_REGISTER_ACTION))
+
+ test
+ .assertState(initialState)
+ .assertEvents(OnboardingViewEvents.RegistrationFlowResult(ANY_CONTINUING_REGISTRATION_RESULT.flowResult, isRegistrationStarted = true))
+ .finish()
+ }
+
+ @Test
+ fun `given register action ignores result, when handling action, then does nothing on success`() = runTest {
+ val test = viewModel.test()
+ givenRegistrationResultFor(A_RESULT_IGNORED_REGISTER_ACTION, RegistrationResult.FlowResponse(AN_IGNORED_FLOW_RESULT))
+
+ viewModel.handle(OnboardingAction.PostRegisterAction(A_RESULT_IGNORED_REGISTER_ACTION))
+
+ test
+ .assertStatesChanges(
+ initialState,
+ { copy(asyncRegistration = Loading()) },
+ { copy(asyncRegistration = Uninitialized) }
+ )
+ .assertNoEvents()
+ .finish()
+ }
+
+ @Test
+ fun `when registering account, then updates state and emits account created event`() = runTest {
+ givenRegistrationResultFor(A_LOADABLE_REGISTER_ACTION, RegistrationResult.Success(fakeSession))
+ givenSuccessfullyCreatesAccount(A_HOMESERVER_CAPABILITIES)
+ val test = viewModel.test()
+
+ viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
+
+ test
+ .assertStatesChanges(
+ initialState,
+ { copy(asyncRegistration = Loading()) },
+ { copy(asyncLoginAction = Success(Unit), personalizationState = A_HOMESERVER_CAPABILITIES.toPersonalisationState()) },
+ { copy(asyncLoginAction = Success(Unit), asyncRegistration = Uninitialized) }
)
.assertEvents(OnboardingViewEvents.OnAccountCreated)
.finish()
}
@Test
- fun `given changing profile picture is supported when updating display name then updates upstream user display name and moves to choose profile picture`() = runBlockingTest {
+ fun `given registration has started and has dummy step to do, when handling action, then ignores other steps and executes dummy`() = runTest {
+ givenSuccessfulRegistrationForStartAndDummySteps(missingStages = listOf(Stage.Dummy(mandatory = true)))
+ val test = viewModel.test()
+
+ viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
+
+ test
+ .assertStatesChanges(
+ initialState,
+ { copy(asyncRegistration = Loading()) },
+ { copy(asyncLoginAction = Success(Unit), personalizationState = A_HOMESERVER_CAPABILITIES.toPersonalisationState()) },
+ { copy(asyncRegistration = Uninitialized) }
+ )
+ .assertEvents(OnboardingViewEvents.OnAccountCreated)
+ .finish()
+ }
+
+ @Test
+ fun `given changing profile picture is supported, when updating display name, then updates upstream user display name and moves to choose profile picture`() = runTest {
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = true))
viewModel = createViewModel(personalisedInitialState)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
test
- .assertStates(expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState))
+ .assertStatesChanges(personalisedInitialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnChooseProfilePicture)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
}
@Test
- fun `given changing profile picture is not supported when updating display name then updates upstream user display name and completes personalization`() = runBlockingTest {
+ fun `given changing profile picture is not supported, when updating display name, then updates upstream user display name and completes personalization`() = runTest {
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = false))
viewModel = createViewModel(personalisedInitialState)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
test
- .assertStates(expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState))
+ .assertStatesChanges(personalisedInitialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnPersonalizationComplete)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
}
@Test
- fun `given upstream failure when handling display name update then emits failure event`() = runBlockingTest {
- val test = viewModel.test(this)
+ fun `given upstream failure, when handling display name update, then emits failure event`() = runTest {
+ val test = viewModel.test()
fakeSession.fakeProfileService.givenSetDisplayNameErrors(AN_ERROR)
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
test
- .assertStates(
+ .assertStatesChanges(
initialState,
- initialState.copy(asyncDisplayName = Loading()),
- initialState.copy(asyncDisplayName = Fail(AN_ERROR)),
+ { copy(asyncDisplayName = Loading()) },
+ { copy(asyncDisplayName = Fail(AN_ERROR)) },
)
.assertEvents(OnboardingViewEvents.Failure(AN_ERROR))
.finish()
}
@Test
- fun `when handling profile picture selected then updates selected picture state`() = runBlockingTest {
- val test = viewModel.test(this)
+ fun `when handling profile picture selected, then updates selected picture state`() = runTest {
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.ProfilePictureSelected(fakeUri.instance))
@@ -198,10 +283,10 @@ class OnboardingViewModelTest {
}
@Test
- fun `given a selected picture when handling save selected profile picture then updates upstream avatar and completes personalization`() = runBlockingTest {
+ fun `given a selected picture, when handling save selected profile picture, then updates upstream avatar and completes personalization`() = runTest {
val initialStateWithPicture = givenPictureSelected(fakeUri.instance, A_PICTURE_FILENAME)
viewModel = createViewModel(initialStateWithPicture)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@@ -213,11 +298,11 @@ class OnboardingViewModelTest {
}
@Test
- fun `given upstream update avatar fails when saving selected profile picture then emits failure event`() = runBlockingTest {
+ fun `given upstream update avatar fails, when saving selected profile picture, then emits failure event`() = runTest {
fakeSession.fakeProfileService.givenUpdateAvatarErrors(AN_ERROR)
val initialStateWithPicture = givenPictureSelected(fakeUri.instance, A_PICTURE_FILENAME)
viewModel = createViewModel(initialStateWithPicture)
- val test = viewModel.test(this)
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@@ -228,8 +313,8 @@ class OnboardingViewModelTest {
}
@Test
- fun `given no selected picture when saving selected profile picture then emits failure event`() = runBlockingTest {
- val test = viewModel.test(this)
+ fun `given no selected picture, when saving selected profile picture, then emits failure event`() = runTest {
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@@ -240,8 +325,8 @@ class OnboardingViewModelTest {
}
@Test
- fun `when handling profile picture skipped then completes personalization`() = runBlockingTest {
- val test = viewModel.test(this)
+ fun `when handling profile skipped, then completes personalization`() = runTest {
+ val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateProfilePictureSkipped)
@@ -264,6 +349,7 @@ class OnboardingViewModelTest {
FakeVectorFeatures(),
FakeAnalyticsTracker(),
fakeUriFilenameResolver.instance,
+ fakeRegisterActionHandler.instance,
FakeVectorOverrides()
)
}
@@ -286,22 +372,42 @@ class OnboardingViewModelTest {
state.copy(asyncProfilePicture = Fail(cause))
)
- private fun givenSuccessfullyCreatesAccount() {
+ private fun expectedSuccessfulDisplayNameUpdateStates(): List OnboardingViewState> {
+ return listOf(
+ { copy(asyncDisplayName = Loading()) },
+ { copy(asyncDisplayName = Success(Unit), personalizationState = personalizationState.copy(displayName = A_DISPLAY_NAME)) }
+ )
+ }
+
+ private fun givenSuccessfulRegistrationForStartAndDummySteps(missingStages: List) {
+ val flowResult = FlowResult(missingStages = missingStages, completedStages = emptyList())
+ givenRegistrationResultsFor(listOf(
+ A_LOADABLE_REGISTER_ACTION to RegistrationResult.FlowResponse(flowResult),
+ RegisterAction.RegisterDummy to RegistrationResult.Success(fakeSession)
+ ))
+ givenSuccessfullyCreatesAccount(A_HOMESERVER_CAPABILITIES)
+ }
+
+ private fun givenSuccessfullyCreatesAccount(homeServerCapabilities: HomeServerCapabilities) {
+ fakeSession.fakeHomeServerCapabilitiesService.givenCapabilities(homeServerCapabilities)
fakeActiveSessionHolder.expectSetsActiveSession(fakeSession)
- val registrationWizard = FakeRegistrationWizard().also { it.givenSuccessfulDummy(fakeSession) }
- fakeAuthenticationService.givenRegistrationWizard(registrationWizard)
fakeAuthenticationService.expectReset()
fakeSession.expectStartsSyncing()
}
- private fun expectedSuccessfulDisplayNameUpdateStates(personalisedInitialState: OnboardingViewState): List {
- return listOf(
- personalisedInitialState,
- personalisedInitialState.copy(asyncDisplayName = Loading()),
- personalisedInitialState.copy(
- asyncDisplayName = Success(Unit),
- personalizationState = personalisedInitialState.personalizationState.copy(displayName = A_DISPLAY_NAME)
- )
- )
+ private fun givenRegistrationResultFor(action: RegisterAction, result: RegistrationResult) {
+ givenRegistrationResultsFor(listOf(action to result))
+ }
+
+ private fun givenRegistrationResultsFor(results: List>) {
+ fakeAuthenticationService.givenRegistrationStarted(true)
+ val registrationWizard = FakeRegistrationWizard()
+ fakeAuthenticationService.givenRegistrationWizard(registrationWizard)
+ fakeRegisterActionHandler.givenResultsFor(registrationWizard, results)
}
}
+
+private fun HomeServerCapabilities.toPersonalisationState() = PersonalizationState(
+ supportsChangingDisplayName = canChangeDisplayName,
+ supportsChangingProfilePicture = canChangeAvatar
+)
diff --git a/vector/src/test/java/im/vector/app/features/onboarding/RegistrationActionHandlerTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/RegistrationActionHandlerTest.kt
new file mode 100644
index 0000000000..a7fa2a6331
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/onboarding/RegistrationActionHandlerTest.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.onboarding
+
+import im.vector.app.test.fakes.FakeRegistrationWizard
+import im.vector.app.test.fakes.FakeSession
+import io.mockk.coVerifyAll
+import kotlinx.coroutines.test.runTest
+import org.amshove.kluent.shouldBeEqualTo
+import org.junit.Test
+import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
+
+private val A_SESSION = FakeSession()
+private val AN_EXPECTED_RESULT = RegistrationResult.Success(A_SESSION)
+private const val A_USERNAME = "a username"
+private const val A_PASSWORD = "a password"
+private const val AN_INITIAL_DEVICE_NAME = "a device name"
+private const val A_CAPTCHA_RESPONSE = "a captcha response"
+private const val A_PID_CODE = "a pid code"
+private const val EMAIL_VALIDATED_DELAY = 10000L
+private val A_PID_TO_REGISTER = RegisterThreePid.Email("an email")
+
+class RegistrationActionHandlerTest {
+
+ @Test
+ fun `when handling register action then delegates to wizard`() = runTest {
+ val cases = listOf(
+ case(RegisterAction.StartRegistration) { getRegistrationFlow() },
+ case(RegisterAction.CaptchaDone(A_CAPTCHA_RESPONSE)) { performReCaptcha(A_CAPTCHA_RESPONSE) },
+ case(RegisterAction.AcceptTerms) { acceptTerms() },
+ case(RegisterAction.RegisterDummy) { dummy() },
+ case(RegisterAction.AddThreePid(A_PID_TO_REGISTER)) { addThreePid(A_PID_TO_REGISTER) },
+ case(RegisterAction.SendAgainThreePid) { sendAgainThreePid() },
+ case(RegisterAction.ValidateThreePid(A_PID_CODE)) { handleValidateThreePid(A_PID_CODE) },
+ case(RegisterAction.CheckIfEmailHasBeenValidated(EMAIL_VALIDATED_DELAY)) { checkIfEmailHasBeenValidated(EMAIL_VALIDATED_DELAY) },
+ case(RegisterAction.CreateAccount(A_USERNAME, A_PASSWORD, AN_INITIAL_DEVICE_NAME)) {
+ createAccount(A_USERNAME, A_PASSWORD, AN_INITIAL_DEVICE_NAME)
+ }
+ )
+
+ cases.forEach { testSuccessfulActionDelegation(it) }
+ }
+
+ private suspend fun testSuccessfulActionDelegation(case: Case) {
+ val registrationActionHandler = RegistrationActionHandler()
+ val fakeRegistrationWizard = FakeRegistrationWizard()
+ fakeRegistrationWizard.givenSuccessFor(result = A_SESSION, case.expect)
+
+ val result = registrationActionHandler.handleRegisterAction(fakeRegistrationWizard, case.action)
+
+ coVerifyAll { case.expect(fakeRegistrationWizard) }
+ result shouldBeEqualTo AN_EXPECTED_RESULT
+ }
+}
+
+private fun case(action: RegisterAction, expect: suspend RegistrationWizard.() -> RegistrationResult) = Case(action, expect)
+
+private class Case(val action: RegisterAction, val expect: suspend RegistrationWizard.() -> RegistrationResult)
diff --git a/vector/src/test/java/im/vector/app/test/Extensions.kt b/vector/src/test/java/im/vector/app/test/Extensions.kt
index 3ff041dc11..b9521298e2 100644
--- a/vector/src/test/java/im/vector/app/test/Extensions.kt
+++ b/vector/src/test/java/im/vector/app/test/Extensions.kt
@@ -21,12 +21,14 @@ import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
fun String.trimIndentOneLine() = trimIndent().replace("\n", "")
-fun VectorViewModel.test(coroutineScope: CoroutineScope): ViewModelTest {
- val state = stateFlow.test(coroutineScope)
- val viewEvents = viewEvents.stream().test(coroutineScope)
+fun VectorViewModel.test(): ViewModelTest {
+ val testResultCollectingScope = CoroutineScope(Dispatchers.Unconfined)
+ val state = stateFlow.test(testResultCollectingScope)
+ val viewEvents = viewEvents.stream().test(testResultCollectingScope)
return ViewModelTest(state, viewEvents)
}
@@ -55,6 +57,25 @@ class ViewModelTest(
return this
}
+ fun assertStatesChanges(initial: S, vararg expected: S.() -> S): ViewModelTest {
+ return assertStatesChanges(initial, expected.toList())
+ }
+
+ /**
+ * Asserts the expected states are in the same order as the actual state emissions
+ * Each expected lambda is given the previous expected state, starting with the initial
+ */
+ fun assertStatesChanges(initial: S, expected: List S>): ViewModelTest {
+ val reducedExpectedStates = expected.fold(mutableListOf(initial)) { acc, curr ->
+ val next = curr.invoke(acc.last())
+ acc.add(next)
+ acc
+ }
+
+ states.assertValues(reducedExpectedStates)
+ return this
+ }
+
fun assertStates(expected: List): ViewModelTest {
states.assertValues(expected)
return this
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt
index e1a605c7df..10daf5de1e 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt
@@ -23,10 +23,15 @@ import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
class FakeAuthenticationService : AuthenticationService by mockk() {
+
fun givenRegistrationWizard(registrationWizard: RegistrationWizard) {
every { getRegistrationWizard() } returns registrationWizard
}
+ fun givenRegistrationStarted(started: Boolean) {
+ every { isRegistrationStarted } returns started
+ }
+
fun expectReset() {
coJustRun { reset() }
}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRegisterActionHandler.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRegisterActionHandler.kt
new file mode 100644
index 0000000000..8d595d91e9
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRegisterActionHandler.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.test.fakes
+
+import im.vector.app.features.onboarding.RegisterAction
+import im.vector.app.features.onboarding.RegistrationActionHandler
+import io.mockk.coEvery
+import io.mockk.mockk
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
+
+class FakeRegisterActionHandler {
+
+ val instance = mockk()
+
+ fun givenResultsFor(wizard: RegistrationWizard, result: List>) {
+ coEvery { instance.handleRegisterAction(wizard, any()) } answers { call ->
+ val actionArg = call.invocation.args[1] as RegisterAction
+ result.first { it.first == actionArg }.second
+ }
+ }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt
index 6ae394eea1..4e6e511abb 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt
@@ -22,9 +22,9 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationResult
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
import org.matrix.android.sdk.api.session.Session
-class FakeRegistrationWizard : RegistrationWizard by mockk() {
+class FakeRegistrationWizard : RegistrationWizard by mockk(relaxed = false) {
- fun givenSuccessfulDummy(session: Session) {
- coEvery { dummy() } returns RegistrationResult.Success(session)
+ fun givenSuccessFor(result: Session, expect: suspend RegistrationWizard.() -> RegistrationResult) {
+ coEvery { expect(this@FakeRegistrationWizard) } returns RegistrationResult.Success(result)
}
}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorFeatures.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorFeatures.kt
index 265941a531..b6e06bcdda 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeVectorFeatures.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeVectorFeatures.kt
@@ -23,5 +23,5 @@ class FakeVectorFeatures : VectorFeatures {
override fun isOnboardingAlreadyHaveAccountSplashEnabled() = true
override fun isOnboardingSplashCarouselEnabled() = true
override fun isOnboardingUseCaseEnabled() = true
- override fun isOnboardingPersonalizeEnabled() = false
+ override fun isOnboardingPersonalizeEnabled() = true
}
diff --git a/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt
new file mode 100644
index 0000000000..a4d9869a89
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.test.fixtures
+
+import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
+import org.matrix.android.sdk.api.session.homeserver.RoomVersionCapabilities
+
+fun aHomeServerCapabilities(
+ canChangePassword: Boolean = true,
+ canChangeDisplayName: Boolean = true,
+ canChangeAvatar: Boolean = true,
+ canChange3pid: Boolean = true,
+ maxUploadFileSize: Long = 100L,
+ lastVersionIdentityServerSupported: Boolean = false,
+ defaultIdentityServerUrl: String? = null,
+ roomVersions: RoomVersionCapabilities? = null
+) = HomeServerCapabilities(
+ canChangePassword,
+ canChangeDisplayName,
+ canChangeAvatar,
+ canChange3pid,
+ maxUploadFileSize,
+ lastVersionIdentityServerSupported,
+ defaultIdentityServerUrl,
+ roomVersions
+)