Merge pull request #2444 from vector-im/feature/bca/deeplink_mxto
Fix issues with matrix.to deep linking
This commit is contained in:
commit
bc889cbcf4
|
@ -35,6 +35,11 @@ interface UserService {
|
||||||
*/
|
*/
|
||||||
fun getUser(userId: String): User?
|
fun getUser(userId: String): User?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to resolve user from known users, or using profile api
|
||||||
|
*/
|
||||||
|
fun resolveUser(userId: String, callback: MatrixCallback<User>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search list of users on server directory.
|
* Search list of users on server directory.
|
||||||
* @param search the searched term
|
* @param search the searched term
|
||||||
|
|
|
@ -19,10 +19,13 @@ package org.matrix.android.sdk.internal.session.user
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.paging.PagedList
|
import androidx.paging.PagedList
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.profile.ProfileService
|
||||||
import org.matrix.android.sdk.api.session.user.UserService
|
import org.matrix.android.sdk.api.session.user.UserService
|
||||||
import org.matrix.android.sdk.api.session.user.model.User
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateIgnoredUserIdsTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateIgnoredUserIdsTask
|
||||||
import org.matrix.android.sdk.internal.session.user.model.SearchUserTask
|
import org.matrix.android.sdk.internal.session.user.model.SearchUserTask
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||||
|
@ -32,12 +35,40 @@ import javax.inject.Inject
|
||||||
internal class DefaultUserService @Inject constructor(private val userDataSource: UserDataSource,
|
internal class DefaultUserService @Inject constructor(private val userDataSource: UserDataSource,
|
||||||
private val searchUserTask: SearchUserTask,
|
private val searchUserTask: SearchUserTask,
|
||||||
private val updateIgnoredUserIdsTask: UpdateIgnoredUserIdsTask,
|
private val updateIgnoredUserIdsTask: UpdateIgnoredUserIdsTask,
|
||||||
|
private val getProfileInfoTask: GetProfileInfoTask,
|
||||||
private val taskExecutor: TaskExecutor) : UserService {
|
private val taskExecutor: TaskExecutor) : UserService {
|
||||||
|
|
||||||
override fun getUser(userId: String): User? {
|
override fun getUser(userId: String): User? {
|
||||||
return userDataSource.getUser(userId)
|
return userDataSource.getUser(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun resolveUser(userId: String, callback: MatrixCallback<User>) {
|
||||||
|
val known = getUser(userId)
|
||||||
|
if (known != null) {
|
||||||
|
callback.onSuccess(known)
|
||||||
|
} else {
|
||||||
|
val params = GetProfileInfoTask.Params(userId)
|
||||||
|
getProfileInfoTask
|
||||||
|
.configureWith(params) {
|
||||||
|
this.callback = object : MatrixCallback<JsonDict> {
|
||||||
|
override fun onSuccess(data: JsonDict) {
|
||||||
|
callback.onSuccess(
|
||||||
|
User(
|
||||||
|
userId,
|
||||||
|
data[ProfileService.DISPLAY_NAME_KEY] as? String,
|
||||||
|
data[ProfileService.AVATAR_URL_KEY] as? String)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
callback.onFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getUserLive(userId: String): LiveData<Optional<User>> {
|
override fun getUserLive(userId: String): LiveData<Optional<User>> {
|
||||||
return userDataSource.getUserLive(userId)
|
return userDataSource.getUserLive(userId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
android:resource="@xml/shortcuts" />
|
android:resource="@xml/shortcuts" />
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
|
||||||
<activity android:name=".features.home.HomeActivity" />
|
<activity android:name=".features.home.HomeActivity"
|
||||||
|
android:launchMode="singleTask"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.login.LoginActivity"
|
android:name=".features.login.LoginActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
|
@ -189,10 +190,9 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.signout.soft.SoftLogoutActivity"
|
android:name=".features.signout.soft.SoftLogoutActivity"
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity android:name=".features.permalink.PermalinkHandlerActivity">
|
<activity android:name=".features.permalink.PermalinkHandlerActivity" android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.home
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
@ -38,8 +39,12 @@ import im.vector.app.core.extensions.replaceFragment
|
||||||
import im.vector.app.core.platform.ToolbarConfigurable
|
import im.vector.app.core.platform.ToolbarConfigurable
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
|
import im.vector.app.core.utils.toast
|
||||||
import im.vector.app.features.disclaimer.showDisclaimerDialog
|
import im.vector.app.features.disclaimer.showDisclaimerDialog
|
||||||
|
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
||||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||||
|
import im.vector.app.features.permalink.NavigationInterceptor
|
||||||
|
import im.vector.app.features.permalink.PermalinkHandler
|
||||||
import im.vector.app.features.popup.DefaultVectorAlert
|
import im.vector.app.features.popup.DefaultVectorAlert
|
||||||
import im.vector.app.features.popup.PopupAlertManager
|
import im.vector.app.features.popup.PopupAlertManager
|
||||||
import im.vector.app.features.popup.VerificationVectorAlert
|
import im.vector.app.features.popup.VerificationVectorAlert
|
||||||
|
@ -50,10 +55,12 @@ import im.vector.app.features.themes.ThemeUtils
|
||||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
||||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
|
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
|
||||||
import im.vector.app.push.fcm.FcmHelper
|
import im.vector.app.push.fcm.FcmHelper
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import kotlinx.android.synthetic.main.activity_home.*
|
import kotlinx.android.synthetic.main.activity_home.*
|
||||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||||
import org.matrix.android.sdk.api.session.InitialSyncProgressService
|
import org.matrix.android.sdk.api.session.InitialSyncProgressService
|
||||||
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -64,7 +71,8 @@ data class HomeActivityArgs(
|
||||||
val accountCreation: Boolean
|
val accountCreation: Boolean
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDetectorSharedViewModel.Factory, ServerBackupStatusViewModel.Factory {
|
class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDetectorSharedViewModel.Factory, ServerBackupStatusViewModel.Factory,
|
||||||
|
NavigationInterceptor {
|
||||||
|
|
||||||
private lateinit var sharedActionViewModel: HomeSharedActionViewModel
|
private lateinit var sharedActionViewModel: HomeSharedActionViewModel
|
||||||
|
|
||||||
|
@ -82,6 +90,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
@Inject lateinit var popupAlertManager: PopupAlertManager
|
@Inject lateinit var popupAlertManager: PopupAlertManager
|
||||||
@Inject lateinit var shortcutsHandler: ShortcutsHandler
|
@Inject lateinit var shortcutsHandler: ShortcutsHandler
|
||||||
@Inject lateinit var unknownDeviceViewModelFactory: UnknownDeviceDetectorSharedViewModel.Factory
|
@Inject lateinit var unknownDeviceViewModelFactory: UnknownDeviceDetectorSharedViewModel.Factory
|
||||||
|
@Inject lateinit var permalinkHandler: PermalinkHandler
|
||||||
|
|
||||||
private val drawerListener = object : DrawerLayout.SimpleDrawerListener() {
|
private val drawerListener = object : DrawerLayout.SimpleDrawerListener() {
|
||||||
override fun onDrawerStateChanged(newState: Int) {
|
override fun onDrawerStateChanged(newState: Int) {
|
||||||
|
@ -145,6 +154,28 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
|
|
||||||
shortcutsHandler.observeRoomsAndBuildShortcuts()
|
shortcutsHandler.observeRoomsAndBuildShortcuts()
|
||||||
.disposeOnDestroy()
|
.disposeOnDestroy()
|
||||||
|
|
||||||
|
if (isFirstCreation()) {
|
||||||
|
handleIntent(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent(intent: Intent?) {
|
||||||
|
intent?.dataString?.let { deepLink ->
|
||||||
|
if (!deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE)) return@let
|
||||||
|
|
||||||
|
permalinkHandler.launch(this, deepLink,
|
||||||
|
navigationInterceptor = this,
|
||||||
|
buildTask = true)
|
||||||
|
// .delay(500, TimeUnit.MILLISECONDS)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { isHandled ->
|
||||||
|
if (!isHandled) {
|
||||||
|
toast(R.string.permalink_malformed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disposeOnDestroy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderState(state: HomeActivityViewState) {
|
private fun renderState(state: HomeActivityViewState) {
|
||||||
|
@ -270,6 +301,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
if (intent?.getParcelableExtra<HomeActivityArgs>(MvRx.KEY_ARG)?.clearNotification == true) {
|
if (intent?.getParcelableExtra<HomeActivityArgs>(MvRx.KEY_ARG)?.clearNotification == true) {
|
||||||
notificationDrawerManager.clearAllEvents()
|
notificationDrawerManager.clearAllEvents()
|
||||||
}
|
}
|
||||||
|
handleIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -334,6 +366,18 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun navToMemberProfile(userId: String, deepLink: Uri): Boolean {
|
||||||
|
val listener = object : MatrixToBottomSheet.InteractionListener {
|
||||||
|
override fun navigateToRoom(roomId: String) {
|
||||||
|
navigator.openRoom(this@HomeActivity, roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO check if there is already one??
|
||||||
|
MatrixToBottomSheet.withLink(deepLink.toString(), listener)
|
||||||
|
.show(supportFragmentManager, "HA#MatrixToBottomSheet")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newIntent(context: Context, clearNotification: Boolean = false, accountCreation: Boolean = false): Intent {
|
fun newIntent(context: Context, clearNotification: Boolean = false, accountCreation: Boolean = false): Intent {
|
||||||
val args = HomeActivityArgs(
|
val args = HomeActivityArgs(
|
||||||
|
|
|
@ -1460,7 +1460,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navToMemberProfile(userId: String): Boolean {
|
override fun navToMemberProfile(userId: String, deepLink: Uri): Boolean {
|
||||||
openRoomMemberProfile(userId)
|
openRoomMemberProfile(userId)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.matrixto
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
|
sealed class MatrixToAction : VectorViewModelAction {
|
||||||
|
data class StartChattingWithUser(val matrixItem: MatrixItem) : MatrixToAction()
|
||||||
|
}
|
|
@ -17,23 +17,37 @@
|
||||||
package im.vector.app.features.matrixto
|
package im.vector.app.features.matrixto
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.core.view.isInvisible
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.MvRx
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import com.airbnb.mvrx.withState
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.di.ScreenComponent
|
import im.vector.app.core.di.ScreenComponent
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_matrix_to_card.*
|
import kotlinx.android.synthetic.main.bottom_sheet_matrix_to_card.*
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MatrixToBottomSheet(private val matrixItem: MatrixItem) : VectorBaseBottomSheetDialogFragment() {
|
class MatrixToBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class MatrixToArgs(
|
||||||
|
val matrixToLink: String
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||||
|
|
||||||
interface InteractionListener {
|
@Inject
|
||||||
fun didTapStartMessage(matrixItem: MatrixItem)
|
lateinit var matrixToBottomSheetViewModelFactory: MatrixToBottomSheetViewModel.Factory
|
||||||
}
|
|
||||||
|
|
||||||
override fun injectWith(injector: ScreenComponent) {
|
override fun injectWith(injector: ScreenComponent) {
|
||||||
injector.inject(this)
|
injector.inject(this)
|
||||||
|
@ -43,21 +57,87 @@ class MatrixToBottomSheet(private val matrixItem: MatrixItem) : VectorBaseBottom
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.bottom_sheet_matrix_to_card
|
override fun getLayoutResId() = R.layout.bottom_sheet_matrix_to_card
|
||||||
|
|
||||||
|
private val viewModel by fragmentViewModel(MatrixToBottomSheetViewModel::class)
|
||||||
|
|
||||||
|
interface InteractionListener {
|
||||||
|
fun navigateToRoom(roomId: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
|
super.invalidate()
|
||||||
|
when (val item = state.matrixItem) {
|
||||||
|
Uninitialized -> {
|
||||||
|
matrixToCardContentLoading.isVisible = false
|
||||||
|
matrixToCardUserContentVisibility.isVisible = false
|
||||||
|
}
|
||||||
|
is Loading -> {
|
||||||
|
matrixToCardContentLoading.isVisible = true
|
||||||
|
matrixToCardUserContentVisibility.isVisible = false
|
||||||
|
}
|
||||||
|
is Success -> {
|
||||||
|
matrixToCardContentLoading.isVisible = false
|
||||||
|
matrixToCardUserContentVisibility.isVisible = true
|
||||||
|
matrixToCardNameText.setTextOrHide(item.invoke().displayName)
|
||||||
|
matrixToCardUserIdText.setTextOrHide(item.invoke().id)
|
||||||
|
avatarRenderer.render(item.invoke(), matrixToCardAvatar)
|
||||||
|
}
|
||||||
|
is Fail -> {
|
||||||
|
// TODO display some error copy?
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (state.startChattingState) {
|
||||||
|
Uninitialized -> {
|
||||||
|
matrixToCardButtonLoading.isVisible = false
|
||||||
|
matrixToCardSendMessageButton.isVisible = false
|
||||||
|
}
|
||||||
|
is Success -> {
|
||||||
|
matrixToCardButtonLoading.isVisible = false
|
||||||
|
matrixToCardSendMessageButton.isVisible = true
|
||||||
|
}
|
||||||
|
is Fail -> {
|
||||||
|
matrixToCardButtonLoading.isVisible = false
|
||||||
|
matrixToCardSendMessageButton.isVisible = true
|
||||||
|
// TODO display some error copy?
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
is Loading -> {
|
||||||
|
matrixToCardButtonLoading.isVisible = true
|
||||||
|
matrixToCardSendMessageButton.isInvisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
matrixToCardSendMessageButton.debouncedClicks {
|
matrixToCardSendMessageButton.debouncedClicks {
|
||||||
interactionListener?.didTapStartMessage(matrixItem)
|
withState(viewModel) {
|
||||||
dismiss()
|
it.matrixItem.invoke()?.let { item ->
|
||||||
|
viewModel.handle(MatrixToAction.StartChattingWithUser(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matrixToCardNameText.setTextOrHide(matrixItem.displayName)
|
viewModel.observeViewEvents {
|
||||||
matrixToCardUserIdText.setTextOrHide(matrixItem.id)
|
when (it) {
|
||||||
avatarRenderer.render(matrixItem, matrixToCardAvatar)
|
is MatrixToViewEvents.NavigateToRoom -> {
|
||||||
|
interactionListener?.navigateToRoom(it.roomId)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
MatrixToViewEvents.Dismiss -> dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(matrixItem: MatrixItem, listener: InteractionListener?): MatrixToBottomSheet {
|
fun withLink(matrixToLink: String, listener: InteractionListener?): MatrixToBottomSheet {
|
||||||
return MatrixToBottomSheet(matrixItem).apply {
|
return MatrixToBottomSheet().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putParcelable(MvRx.KEY_ARG, MatrixToBottomSheet.MatrixToArgs(
|
||||||
|
matrixToLink = matrixToLink
|
||||||
|
))
|
||||||
|
}
|
||||||
interactionListener = listener
|
interactionListener = listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.matrixto
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
|
data class MatrixToBottomSheetState(
|
||||||
|
val deepLink: String,
|
||||||
|
val matrixItem: Async<MatrixItem> = Uninitialized,
|
||||||
|
val startChattingState: Async<Unit> = Uninitialized
|
||||||
|
) : MvRxState {
|
||||||
|
|
||||||
|
constructor(args: MatrixToBottomSheet.MatrixToArgs) : this(
|
||||||
|
deepLink = args.matrixToLink
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.matrixto
|
||||||
|
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
|
import com.squareup.inject.assisted.Assisted
|
||||||
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
import im.vector.app.R
|
||||||
|
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.raw.wellknown.getElementWellknown
|
||||||
|
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
|
||||||
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
|
|
||||||
|
class MatrixToBottomSheetViewModel @AssistedInject constructor(
|
||||||
|
@Assisted initialState: MatrixToBottomSheetState,
|
||||||
|
private val session: Session,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val rawService: RawService) : VectorViewModel<MatrixToBottomSheetState, MatrixToAction, MatrixToViewEvents>(initialState) {
|
||||||
|
|
||||||
|
@AssistedInject.Factory
|
||||||
|
interface Factory {
|
||||||
|
fun create(initialState: MatrixToBottomSheetState): MatrixToBottomSheetViewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
setState {
|
||||||
|
copy(matrixItem = Loading())
|
||||||
|
}
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
resolveLink(initialState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun resolveLink(initialState: MatrixToBottomSheetState) {
|
||||||
|
val permalinkData = PermalinkParser.parse(initialState.deepLink)
|
||||||
|
if (permalinkData is PermalinkData.FallbackLink) {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
matrixItem = Fail(IllegalArgumentException(stringProvider.getString(R.string.permalink_malformed))),
|
||||||
|
startChattingState = Uninitialized
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
when (permalinkData) {
|
||||||
|
is PermalinkData.UserLink -> {
|
||||||
|
val user = resolveUser(permalinkData.userId)
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
matrixItem = Success(user.toMatrixItem()),
|
||||||
|
startChattingState = Success(Unit)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is PermalinkData.RoomLink -> {
|
||||||
|
// not yet supported
|
||||||
|
_viewEvents.post(MatrixToViewEvents.Dismiss)
|
||||||
|
}
|
||||||
|
is PermalinkData.GroupLink -> {
|
||||||
|
// not yet supported
|
||||||
|
_viewEvents.post(MatrixToViewEvents.Dismiss)
|
||||||
|
}
|
||||||
|
is PermalinkData.FallbackLink -> {
|
||||||
|
_viewEvents.post(MatrixToViewEvents.Dismiss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun resolveUser(userId: String): User {
|
||||||
|
return tryOrNull {
|
||||||
|
awaitCallback<User> {
|
||||||
|
session.resolveUser(userId, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create raw user in case the user is not searchable
|
||||||
|
?: User(userId, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : MvRxViewModelFactory<MatrixToBottomSheetViewModel, MatrixToBottomSheetState> {
|
||||||
|
override fun create(viewModelContext: ViewModelContext, state: MatrixToBottomSheetState): MatrixToBottomSheetViewModel? {
|
||||||
|
val fragment: MatrixToBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
|
||||||
|
|
||||||
|
return fragment.matrixToBottomSheetViewModelFactory.create(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handle(action: MatrixToAction) {
|
||||||
|
when (action) {
|
||||||
|
is MatrixToAction.StartChattingWithUser -> handleStartChatting(action)
|
||||||
|
}.exhaustive
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleStartChatting(action: MatrixToAction.StartChattingWithUser) {
|
||||||
|
val mxId = action.matrixItem.id
|
||||||
|
val existing = session.getExistingDirectRoomWithUser(mxId)
|
||||||
|
if (existing != null) {
|
||||||
|
// navigate to this room
|
||||||
|
_viewEvents.post(MatrixToViewEvents.NavigateToRoom(existing))
|
||||||
|
} else {
|
||||||
|
setState {
|
||||||
|
copy(startChattingState = Loading())
|
||||||
|
}
|
||||||
|
// we should create the room then navigate
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val adminE2EByDefault = rawService.getElementWellknown(session.myUserId)
|
||||||
|
?.isE2EByDefault()
|
||||||
|
?: true
|
||||||
|
|
||||||
|
val roomParams = CreateRoomParams()
|
||||||
|
.apply {
|
||||||
|
invitedUserIds.add(mxId)
|
||||||
|
setDirectMessage()
|
||||||
|
enableEncryptionIfInvitedUsersSupportIt = adminE2EByDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
val roomId = try {
|
||||||
|
awaitCallback<String> { session.createRoom(roomParams, it) }
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
setState {
|
||||||
|
copy(startChattingState = Fail(Exception(stringProvider.getString(R.string.invite_users_to_room_failure))))
|
||||||
|
}
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
setState {
|
||||||
|
// we can hide this button has we will navigate out
|
||||||
|
copy(startChattingState = Uninitialized)
|
||||||
|
}
|
||||||
|
_viewEvents.post(MatrixToViewEvents.NavigateToRoom(roomId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.matrixto
|
||||||
|
|
||||||
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
|
||||||
|
sealed class MatrixToViewEvents : VectorViewEvents {
|
||||||
|
data class NavigateToRoom(val roomId: String) : MatrixToViewEvents()
|
||||||
|
object Dismiss : MatrixToViewEvents()
|
||||||
|
}
|
|
@ -63,13 +63,14 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
.subscribeOn(Schedulers.computation())
|
.subscribeOn(Schedulers.computation())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.flatMap { permalinkData ->
|
.flatMap { permalinkData ->
|
||||||
handlePermalink(permalinkData, context, navigationInterceptor, buildTask)
|
handlePermalink(permalinkData, deepLink, context, navigationInterceptor, buildTask)
|
||||||
}
|
}
|
||||||
.onErrorReturnItem(false)
|
.onErrorReturnItem(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handlePermalink(
|
private fun handlePermalink(
|
||||||
permalinkData: PermalinkData,
|
permalinkData: PermalinkData,
|
||||||
|
rawLink: Uri,
|
||||||
context: Context,
|
context: Context,
|
||||||
navigationInterceptor: NavigationInterceptor?,
|
navigationInterceptor: NavigationInterceptor?,
|
||||||
buildTask: Boolean
|
buildTask: Boolean
|
||||||
|
@ -96,7 +97,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
Single.just(true)
|
Single.just(true)
|
||||||
}
|
}
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId) != true) {
|
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId, rawLink) != true) {
|
||||||
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
||||||
}
|
}
|
||||||
Single.just(true)
|
Single.just(true)
|
||||||
|
@ -175,7 +176,7 @@ interface NavigationInterceptor {
|
||||||
/**
|
/**
|
||||||
* Return true if the navigation has been intercepted
|
* Return true if the navigation has been intercepted
|
||||||
*/
|
*/
|
||||||
fun navToMemberProfile(userId: String): Boolean {
|
fun navToMemberProfile(userId: String, deepLink: Uri): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,9 @@ import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.di.ScreenComponent
|
import im.vector.app.core.di.ScreenComponent
|
||||||
import im.vector.app.core.extensions.replaceFragment
|
import im.vector.app.core.extensions.replaceFragment
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.utils.toast
|
import im.vector.app.features.home.HomeActivity
|
||||||
import im.vector.app.features.home.LoadingFragment
|
import im.vector.app.features.home.LoadingFragment
|
||||||
import im.vector.app.features.login.LoginActivity
|
import im.vector.app.features.login.LoginActivity
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PermalinkHandlerActivity : VectorBaseActivity() {
|
class PermalinkHandlerActivity : VectorBaseActivity() {
|
||||||
|
@ -45,23 +43,28 @@ class PermalinkHandlerActivity : VectorBaseActivity() {
|
||||||
if (isFirstCreation()) {
|
if (isFirstCreation()) {
|
||||||
replaceFragment(R.id.simpleFragmentContainer, LoadingFragment::class.java)
|
replaceFragment(R.id.simpleFragmentContainer, LoadingFragment::class.java)
|
||||||
}
|
}
|
||||||
|
handleIntent()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent() {
|
||||||
// If we are not logged in, open login screen.
|
// If we are not logged in, open login screen.
|
||||||
// In the future, we might want to relaunch the process after login.
|
// In the future, we might want to relaunch the process after login.
|
||||||
if (!sessionHolder.hasActiveSession()) {
|
if (!sessionHolder.hasActiveSession()) {
|
||||||
startLoginActivity()
|
startLoginActivity()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val uri = intent.dataString
|
// We forward intent to HomeActivity (singleTask) to avoid the dueling app problem
|
||||||
permalinkHandler.launch(this, uri, buildTask = true)
|
// https://stackoverflow.com/questions/25884954/deep-linking-and-multiple-app-instances
|
||||||
.delay(500, TimeUnit.MILLISECONDS)
|
intent.setClass(this, HomeActivity::class.java)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
.subscribe { isHandled ->
|
startActivity(intent)
|
||||||
if (!isHandled) {
|
|
||||||
toast(R.string.permalink_malformed)
|
|
||||||
}
|
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
.disposeOnDestroy()
|
|
||||||
|
override fun onNewIntent(intent: Intent?) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
handleIntent()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startLoginActivity() {
|
private fun startLoginActivity() {
|
||||||
|
|
|
@ -36,7 +36,6 @@ import im.vector.app.core.utils.onPermissionDeniedSnackbar
|
||||||
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import kotlinx.android.synthetic.main.activity_simple.*
|
import kotlinx.android.synthetic.main.activity_simple.*
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ class UserCodeActivity
|
||||||
UserCodeState.Mode.SCAN -> showFragment(ScanUserCodeFragment::class, Bundle.EMPTY)
|
UserCodeState.Mode.SCAN -> showFragment(ScanUserCodeFragment::class, Bundle.EMPTY)
|
||||||
is UserCodeState.Mode.RESULT -> {
|
is UserCodeState.Mode.RESULT -> {
|
||||||
showFragment(ShowUserCodeFragment::class, Bundle.EMPTY)
|
showFragment(ShowUserCodeFragment::class, Bundle.EMPTY)
|
||||||
MatrixToBottomSheet.create(mode.matrixItem, this).show(supportFragmentManager, "MatrixToBottomSheet")
|
MatrixToBottomSheet.withLink(mode.rawLink, this).show(supportFragmentManager, "MatrixToBottomSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,8 +103,8 @@ class UserCodeActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun didTapStartMessage(matrixItem: MatrixItem) {
|
override fun navigateToRoom(roomId: String) {
|
||||||
sharedViewModel.handle(UserCodeActions.StartChattingWithUser(matrixItem))
|
navigator.openRoom(this, roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() = withState(sharedViewModel) {
|
override fun onBackPressed() = withState(sharedViewModel) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.app.features.raw.wellknown.getElementWellknown
|
||||||
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
import im.vector.app.features.raw.wellknown.isE2EByDefault
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
|
||||||
|
@ -139,22 +140,33 @@ class UserCodeSharedViewModel @AssistedInject constructor(
|
||||||
_viewEvents.post(UserCodeShareViewEvents.ShowWaitingScreen)
|
_viewEvents.post(UserCodeShareViewEvents.ShowWaitingScreen)
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
when (linkedId) {
|
when (linkedId) {
|
||||||
is PermalinkData.RoomLink -> TODO()
|
is PermalinkData.RoomLink -> {
|
||||||
|
// not yet supported
|
||||||
|
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
|
||||||
|
}
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
val user = session.getUser(linkedId.userId) ?: awaitCallback<List<User>> {
|
val user = tryOrNull {
|
||||||
session.searchUsersDirectory(linkedId.userId, 10, emptySet(), it)
|
awaitCallback<User> {
|
||||||
}.firstOrNull { it.userId == linkedId.userId }
|
session.resolveUser(linkedId.userId, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Create raw Uxid in case the user is not searchable
|
// Create raw Uxid in case the user is not searchable
|
||||||
?: User(linkedId.userId, null, null)
|
?: User(linkedId.userId, null, null)
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
mode = UserCodeState.Mode.RESULT(user.toMatrixItem())
|
mode = UserCodeState.Mode.RESULT(user.toMatrixItem(), action.code)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PermalinkData.GroupLink -> TODO()
|
is PermalinkData.GroupLink -> {
|
||||||
is PermalinkData.FallbackLink -> TODO()
|
// not yet supported
|
||||||
|
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
|
||||||
|
}
|
||||||
|
is PermalinkData.FallbackLink -> {
|
||||||
|
// not yet supported
|
||||||
|
_viewEvents.post(UserCodeShareViewEvents.ToastMessage(stringProvider.getString(R.string.not_implemented)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen)
|
_viewEvents.post(UserCodeShareViewEvents.HideWaitingScreen)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ data class UserCodeState(
|
||||||
sealed class Mode {
|
sealed class Mode {
|
||||||
object SHOW : Mode()
|
object SHOW : Mode()
|
||||||
object SCAN : Mode()
|
object SCAN : Mode()
|
||||||
data class RESULT(val matrixItem: MatrixItem) : Mode()
|
data class RESULT(val matrixItem: MatrixItem, val rawLink: String) : Mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(args: UserCodeActivity.Args) : this(
|
constructor(args: UserCodeActivity.Args) : this(
|
||||||
|
|
|
@ -3,13 +3,24 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="200dp">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/matrixToCardContentLoading"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/matrixToCardAvatar"
|
android:id="@+id/matrixToCardAvatar"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
android:transitionName="profile"
|
android:transitionName="profile"
|
||||||
|
@ -63,4 +74,23 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/matrixToCardUserIdText" />
|
app:layout_constraintTop_toBottomOf="@id/matrixToCardUserIdText" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/matrixToCardButtonLoading"
|
||||||
|
style="?android:attr/progressBarStyleSmall"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/matrixToCardSendMessageButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/matrixToCardSendMessageButton"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/matrixToCardSendMessageButton"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/matrixToCardSendMessageButton"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Group
|
||||||
|
android:id="@+id/matrixToCardUserContentVisibility"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:constraint_referenced_ids="matrixToCardAvatar,matrixToCardNameText,matrixToCardUserIdText"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
Loading…
Reference in New Issue