diff --git a/CHANGES.md b/CHANGES.md index 6d72ad4c2a..dafb6cf110 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Features ✨: Improvements 🙌: - Migrate to binary QR code verification (#994) + - Share action is added to room profile and room member profile (#858) Bugfix 🐛: - Account creation: wrongly hints that an email can be used to create an account (#941) diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileAction.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileAction.kt index e352683841..1dc2459538 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileAction.kt @@ -23,4 +23,5 @@ sealed class RoomMemberProfileAction : VectorViewModelAction { object RetryFetchingInfo : RoomMemberProfileAction() object IgnoreUser : RoomMemberProfileAction() object VerifyUser : RoomMemberProfileAction() + object ShareRoomMemberProfile : RoomMemberProfileAction() } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt index 89b37400f1..c62e8ce226 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -19,6 +19,7 @@ package im.vector.riotx.features.roommemberprofile import android.os.Bundle import android.os.Parcelable +import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible @@ -38,6 +39,7 @@ import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.platform.StateView import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.core.utils.startSharePlainTextIntent import im.vector.riotx.features.crypto.verification.VerificationBottomSheet import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.roommemberprofile.devices.DeviceListBottomSheet @@ -65,6 +67,8 @@ class RoomMemberProfileFragment @Inject constructor( override fun getLayoutResId() = R.layout.fragment_matrix_profile + override fun getMenuRes() = R.menu.vector_room_member_profile + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupToolbar(matrixProfileToolbar) @@ -90,14 +94,25 @@ class RoomMemberProfileFragment @Inject constructor( matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener) viewModel.observeViewEvents { when (it) { - is RoomMemberProfileViewEvents.Loading -> showLoading(it.message) - is RoomMemberProfileViewEvents.Failure -> showFailure(it.throwable) - is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit - is RoomMemberProfileViewEvents.StartVerification -> handleStartVerification(it) + is RoomMemberProfileViewEvents.Loading -> showLoading(it.message) + is RoomMemberProfileViewEvents.Failure -> showFailure(it.throwable) + is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit + is RoomMemberProfileViewEvents.StartVerification -> handleStartVerification(it) + is RoomMemberProfileViewEvents.ShareRoomMemberProfile -> handleShareRoomMemberProfile(it.permalink) }.exhaustive } } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.roomMemberProfileShareAction -> { + viewModel.handle(RoomMemberProfileAction.ShareRoomMemberProfile) + return true + } + } + return super.onOptionsItemSelected(item) + } + private fun handleStartVerification(startVerification: RoomMemberProfileViewEvents.StartVerification) { if (startVerification.canCrossSign) { VerificationBottomSheet @@ -208,4 +223,8 @@ class RoomMemberProfileFragment @Inject constructor( override fun onMentionClicked() { vectorBaseActivity.notImplemented("Mention") } + + private fun handleShareRoomMemberProfile(permalink: String) { + startSharePlainTextIntent(fragment = this, chooserTitle = null, text = permalink) + } } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt index 5b7f5bf54c..5d8757a337 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewEvents.kt @@ -31,4 +31,6 @@ sealed class RoomMemberProfileViewEvents : VectorViewEvents { val userId: String, val canCrossSign: Boolean ) : RoomMemberProfileViewEvents() + + data class ShareRoomMemberProfile(val permalink: String) : RoomMemberProfileViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index d6a1018e80..44c214bc99 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -26,6 +26,7 @@ import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.permalinks.PermalinkFactory import im.vector.matrix.android.api.query.QueryStringValue import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.EventType @@ -135,9 +136,10 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v override fun handle(action: RoomMemberProfileAction) { when (action) { - is RoomMemberProfileAction.RetryFetchingInfo -> fetchProfileInfo() - is RoomMemberProfileAction.IgnoreUser -> handleIgnoreAction() - is RoomMemberProfileAction.VerifyUser -> prepareVerification() + is RoomMemberProfileAction.RetryFetchingInfo -> fetchProfileInfo() + is RoomMemberProfileAction.IgnoreUser -> handleIgnoreAction() + is RoomMemberProfileAction.VerifyUser -> prepareVerification() + is RoomMemberProfileAction.ShareRoomMemberProfile -> handleShareRoomMemberProfile() } } @@ -234,4 +236,10 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v session.ignoreUserIds(listOf(state.userId), ignoreActionCallback) } } + + private fun handleShareRoomMemberProfile() { + PermalinkFactory.createPermalink(initialState.userId)?.let { permalink -> + _viewEvents.post(RoomMemberProfileViewEvents.ShareRoomMemberProfile(permalink)) + } + } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileAction.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileAction.kt index d3852e34c8..545d67c314 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileAction.kt @@ -23,4 +23,5 @@ import im.vector.riotx.core.platform.VectorViewModelAction sealed class RoomProfileAction: VectorViewModelAction { object LeaveRoom: RoomProfileAction() data class ChangeRoomNotificationState(val notificationState: RoomNotificationState) : RoomProfileAction() + object ShareRoomProfile : RoomProfileAction() } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt index 1eafc8af3f..2b2a879e7e 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt @@ -19,6 +19,7 @@ package im.vector.riotx.features.roomprofile import android.os.Bundle import android.os.Parcelable +import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible @@ -35,6 +36,7 @@ import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.extensions.setTextOrHide import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.core.utils.startSharePlainTextIntent import im.vector.riotx.features.crypto.util.toImageRes import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.list.actions.RoomListActionsArgs @@ -67,6 +69,8 @@ class RoomProfileFragment @Inject constructor( override fun getLayoutResId() = R.layout.fragment_matrix_profile + override fun getMenuRes() = R.menu.vector_room_profile + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) roomListQuickActionsSharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java) @@ -89,6 +93,7 @@ class RoomProfileFragment @Inject constructor( is RoomProfileViewEvents.Loading -> showLoading(it.message) is RoomProfileViewEvents.Failure -> showFailure(it.throwable) is RoomProfileViewEvents.OnLeaveRoomSuccess -> onLeaveRoom() + is RoomProfileViewEvents.ShareRoomProfile -> onShareRoomProfile(it.permalink) }.exhaustive } roomListQuickActionsSharedActionViewModel @@ -97,6 +102,16 @@ class RoomProfileFragment @Inject constructor( .disposeOnDestroyView() } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.roomProfileShareAction -> { + roomProfileViewModel.handle(RoomProfileAction.ShareRoomProfile) + return true + } + } + return super.onOptionsItemSelected(item) + } + private fun handleQuickActions(action: RoomListQuickActionsSharedAction) = when (action) { is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> { roomProfileViewModel.handle(RoomProfileAction.ChangeRoomNotificationState(RoomNotificationState.ALL_MESSAGES_NOISY)) @@ -187,4 +202,8 @@ class RoomProfileFragment @Inject constructor( .setNegativeButton(R.string.cancel, null) .show() } + + private fun onShareRoomProfile(permalink: String) { + startSharePlainTextIntent(fragment = this, chooserTitle = null, text = permalink) + } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt index 50b3c136e5..7a08a08126 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewEvents.kt @@ -26,4 +26,5 @@ sealed class RoomProfileViewEvents : VectorViewEvents { data class Failure(val throwable: Throwable) : RoomProfileViewEvents() object OnLeaveRoomSuccess : RoomProfileViewEvents() + data class ShareRoomProfile(val permalink: String) : RoomProfileViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt index 6c66ac67b2..d49727d12d 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileViewModel.kt @@ -23,6 +23,7 @@ import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.permalinks.PermalinkFactory import im.vector.matrix.android.api.session.Session import im.vector.matrix.rx.rx import im.vector.matrix.rx.unwrap @@ -30,7 +31,7 @@ import im.vector.riotx.R import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.resources.StringProvider -class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: RoomProfileViewState, +class RoomProfileViewModel @AssistedInject constructor(@Assisted private val initialState: RoomProfileViewState, private val stringProvider: StringProvider, private val session: Session) : VectorViewModel(initialState) { @@ -66,6 +67,7 @@ class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: R override fun handle(action: RoomProfileAction) = when (action) { RoomProfileAction.LeaveRoom -> handleLeaveRoom() is RoomProfileAction.ChangeRoomNotificationState -> handleChangeNotificationMode(action) + is RoomProfileAction.ShareRoomProfile -> handleShareRoomProfile() } private fun handleChangeNotificationMode(action: RoomProfileAction.ChangeRoomNotificationState) { @@ -88,4 +90,10 @@ class RoomProfileViewModel @AssistedInject constructor(@Assisted initialState: R } }) } + + private fun handleShareRoomProfile() { + PermalinkFactory.createPermalink(initialState.roomId)?.let { permalink -> + _viewEvents.post(RoomProfileViewEvents.ShareRoomProfile(permalink)) + } + } } diff --git a/vector/src/main/res/drawable/ic_material_share.xml b/vector/src/main/res/drawable/ic_material_share.xml new file mode 100644 index 0000000000..5ecbfe3388 --- /dev/null +++ b/vector/src/main/res/drawable/ic_material_share.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/vector/src/main/res/layout/fragment_matrix_profile.xml b/vector/src/main/res/layout/fragment_matrix_profile.xml index cf31a6fe60..6e3eca06bf 100644 --- a/vector/src/main/res/layout/fragment_matrix_profile.xml +++ b/vector/src/main/res/layout/fragment_matrix_profile.xml @@ -15,7 +15,7 @@ + + + \ No newline at end of file diff --git a/vector/src/main/res/menu/vector_room_profile.xml b/vector/src/main/res/menu/vector_room_profile.xml new file mode 100644 index 0000000000..f6331018f0 --- /dev/null +++ b/vector/src/main/res/menu/vector_room_profile.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/styles_riot.xml b/vector/src/main/res/values/styles_riot.xml index 76d1988f61..c4b42fe4fe 100644 --- a/vector/src/main/res/values/styles_riot.xml +++ b/vector/src/main/res/values/styles_riot.xml @@ -30,6 +30,10 @@ "sans-serif" + +