track room open and room join analytics events (#5696)

This commit is contained in:
fedrunov 2022-05-03 16:11:40 +02:00 committed by GitHub
parent 8dd87321da
commit 9f520d4e8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 295 additions and 62 deletions

View file

@ -33,18 +33,20 @@ fun Int?.toAnalyticsRoomSize(): JoinedRoom.RoomSize {
}
}
fun RoomSummary?.toAnalyticsJoinedRoom(): JoinedRoom {
fun RoomSummary?.toAnalyticsJoinedRoom(trigger: JoinedRoom.Trigger?): JoinedRoom {
return JoinedRoom(
isDM = this?.isDirect.orFalse(),
isSpace = this?.roomType == RoomType.SPACE,
roomSize = this?.joinedMembersCount?.toAnalyticsRoomSize() ?: JoinedRoom.RoomSize.Two
roomSize = this?.joinedMembersCount?.toAnalyticsRoomSize() ?: JoinedRoom.RoomSize.Two,
trigger = trigger
)
}
fun PublicRoom.toAnalyticsJoinedRoom(): JoinedRoom {
fun PublicRoom.toAnalyticsJoinedRoom(trigger: JoinedRoom.Trigger?): JoinedRoom {
return JoinedRoom(
isDM = false,
isSpace = false,
roomSize = numJoinedMembers.toAnalyticsRoomSize()
roomSize = numJoinedMembers.toAnalyticsRoomSize(),
trigger = trigger
)
}

View file

@ -0,0 +1,44 @@
/*
* 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.analytics.extensions
import im.vector.app.RoomGroupingMethod
import im.vector.app.features.analytics.plan.ViewRoom
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
fun RoomSummary?.toAnalyticsViewRoom(trigger: ViewRoom.Trigger?, groupingMethod: RoomGroupingMethod? = null, viaKeyboard: Boolean? = null): ViewRoom {
val activeSpace = groupingMethod?.let {
when (it) {
is RoomGroupingMethod.BySpace -> it.spaceSummary?.toActiveSpace() ?: ViewRoom.ActiveSpace.Home
else -> null
}
}
return ViewRoom(
isDM = this?.isDirect.orFalse(),
isSpace = this?.roomType == RoomType.SPACE,
trigger = trigger,
activeSpace = activeSpace,
viaKeyboard = viaKeyboard
)
}
private fun RoomSummary.toActiveSpace(): ViewRoom.ActiveSpace {
return if (isPublic) ViewRoom.ActiveSpace.Public else ViewRoom.ActiveSpace.Private
}

View file

@ -43,6 +43,7 @@ import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedSnackbar
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.contactsbook.ContactsBookFragment
import im.vector.app.features.qrcode.QrCodeScannerEvents
import im.vector.app.features.qrcode.QrCodeScannerFragment
@ -206,7 +207,11 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
}
private fun renderCreationSuccess(roomId: String) {
navigator.openRoom(this, roomId)
navigator.openRoom(
context = this,
roomId = roomId,
trigger = ViewRoom.Trigger.MessageUser
)
finish()
}

View file

@ -18,6 +18,7 @@ package im.vector.app.features.crypto.verification
import android.content.Context
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.RoomDetailActivity
@ -156,7 +157,12 @@ class IncomingVerificationRequestHandler @Inject constructor(
if (roomId.isNullOrBlank()) {
it.navigator.waitSessionVerification(it)
} else {
it.navigator.openRoom(it, roomId, pr.transactionId)
it.navigator.openRoom(
context = it,
roomId = roomId,
eventId = pr.transactionId,
trigger = ViewRoom.Trigger.VerificationRequest
)
}
}
}

View file

@ -49,8 +49,10 @@ import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs
import im.vector.app.features.analytics.accountdata.AnalyticsAccountDataViewModel
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.disclaimer.showDisclaimerDialog
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.permalink.NavigationInterceptor
@ -243,7 +245,7 @@ class HomeActivity :
}
if (args?.inviteNotificationRoomId != null) {
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(args.inviteNotificationRoomId)?.let {
navigator.openMatrixToBottomSheet(this, it)
navigator.openMatrixToBottomSheet(this, it, OriginOfMatrixTo.NOTIFICATION)
}
}
@ -480,7 +482,7 @@ class HomeActivity :
activeSessionHolder.getSafeActiveSession()
?.permalinkService()
?.createPermalink(parcelableExtra.inviteNotificationRoomId)?.let {
navigator.openMatrixToBottomSheet(this, it)
navigator.openMatrixToBottomSheet(this, it, OriginOfMatrixTo.NOTIFICATION)
}
}
handleIntent(intent)
@ -567,14 +569,14 @@ class HomeActivity :
override fun navToMemberProfile(userId: String, deepLink: Uri): Boolean {
// TODO check if there is already one??
MatrixToBottomSheet.withLink(deepLink.toString())
MatrixToBottomSheet.withLink(deepLink.toString(), OriginOfMatrixTo.LINK)
.show(supportFragmentManager, "HA#MatrixToBottomSheet")
return true
}
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
if (roomId == null) return false
MatrixToBottomSheet.withLink(deepLink.toString())
MatrixToBottomSheet.withLink(deepLink.toString(), OriginOfMatrixTo.LINK)
.show(supportFragmentManager, "HA#MatrixToBottomSheet")
return true
}
@ -608,8 +610,8 @@ class HomeActivity :
}
}
override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId)
override fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?) {
navigator.openRoom(this, roomId, trigger = trigger)
}
override fun mxToBottomSheetSwitchToSpace(spaceId: String) {

View file

@ -36,6 +36,7 @@ import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityRoomDetailBinding
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
import im.vector.app.features.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
@ -205,8 +206,8 @@ class RoomDetailActivity :
}
}
override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId)
override fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?) {
navigator.openRoom(this, roomId, trigger = trigger)
}
override fun mxToBottomSheetSwitchToSpace(spaceId: String) {

View file

@ -40,6 +40,7 @@ import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.DecryptionFailureTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.call.conference.ConferenceEvent
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
import im.vector.app.features.call.conference.JitsiService
@ -821,13 +822,22 @@ class TimelineViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
session.roomService().joinRoom(room.roomId)
analyticsTracker.capture(room.roomSummary().toAnalyticsJoinedRoom())
trackRoomJoined()
} catch (throwable: Throwable) {
_viewEvents.post(RoomDetailViewEvents.Failure(throwable, showInDialog = true))
}
}
}
private fun trackRoomJoined() {
val trigger = if (initialState.isInviteAlreadyAccepted) {
JoinedRoom.Trigger.Invite
} else {
JoinedRoom.Trigger.Timeline
}
analyticsTracker.capture(room.roomSummary().toAnalyticsJoinedRoom(trigger))
}
private fun handleOpenOrDownloadFile(action: RoomDetailAction.DownloadOrOpen) {
val mxcUrl = action.messageFileContent.getFileUrl() ?: return
val isLocalSendingFile = action.senderId == session.myUserId &&

View file

@ -28,6 +28,7 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsComposer
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.attachments.toContentAttachmentData
import im.vector.app.features.command.CommandParser
import im.vector.app.features.command.ParsedCommand
@ -617,7 +618,7 @@ class MessageComposerViewModel @AssistedInject constructor(
return@launch
}
session.getRoomSummary(command.roomAlias)
?.also { analyticsTracker.capture(it.toAnalyticsJoinedRoom()) }
?.also { analyticsTracker.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.SlashCommand)) }
?.roomId
?.let {
_viewEvents.post(MessageComposerViewEvents.JoinRoomCommandSuccess(it))

View file

@ -37,6 +37,7 @@ import im.vector.app.core.extensions.trackItemsVisibilityChange
import im.vector.app.core.platform.StateView
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSearchBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.events.model.Event
@ -134,7 +135,16 @@ class SearchFragment @Inject constructor(
roomEncryptionTrustLevel = null,
rootThreadEventId = it)
navigator.openThread(requireContext(), threadTimelineArgs, event.eventId)
} ?: navigator.openRoom(requireContext(), roomId, event.eventId)
} ?: openRoom(roomId, event.eventId)
}
private fun openRoom(roomId: String, eventId: String?) {
navigator.openRoom(
context = requireContext(),
roomId = roomId,
eventId = eventId,
trigger = ViewRoom.Trigger.MessageSearch
)
}
override fun loadMore() {

View file

@ -44,12 +44,14 @@ import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.databinding.FragmentRoomListBinding
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.RoomListDisplayMode
import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.notifications.NotificationDrawerManager
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
@ -179,7 +181,7 @@ class RoomListFragment @Inject constructor(
}
private fun handleShowMxToLink(link: String) {
navigator.openMatrixToBottomSheet(requireContext(), link)
navigator.openMatrixToBottomSheet(requireContext(), link, OriginOfMatrixTo.ROOM_LIST)
}
override fun onDestroyView() {
@ -196,7 +198,12 @@ class RoomListFragment @Inject constructor(
}
private fun handleSelectRoom(event: RoomListViewEvents.SelectRoom, isInviteAlreadyAccepted: Boolean) {
navigator.openRoom(context = requireActivity(), roomId = event.roomSummary.roomId, isInviteAlreadyAccepted = isInviteAlreadyAccepted)
navigator.openRoom(
context = requireActivity(),
roomId = event.roomSummary.roomId,
isInviteAlreadyAccepted = isInviteAlreadyAccepted,
trigger = ViewRoom.Trigger.RoomList
)
}
private fun setupCreateRoomButton() {

View file

@ -32,6 +32,8 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
@ -43,6 +45,7 @@ import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
@ -276,6 +279,8 @@ class RoomListViewModel @AssistedInject constructor(
this[action.roomId] = Fail(failure)
}.toMap())
}
session.getRoomSummary(action.roomId)
?.let { analyticsTracker.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.RoomDirectory)) }
}
}

View file

@ -32,6 +32,7 @@ import im.vector.app.R
import im.vector.app.core.extensions.commitTransaction
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetMatrixToCardBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.AvatarRenderer
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
@ -44,7 +45,8 @@ class MatrixToBottomSheet :
@Parcelize
data class MatrixToArgs(
val matrixToLink: String
val matrixToLink: String,
val origin: OriginOfMatrixTo
) : Parcelable
@Inject lateinit var avatarRenderer: AvatarRenderer
@ -58,7 +60,7 @@ class MatrixToBottomSheet :
private val viewModel by fragmentViewModel(MatrixToBottomSheetViewModel::class)
interface InteractionListener {
fun mxToBottomSheetNavigateToRoom(roomId: String)
fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?)
fun mxToBottomSheetSwitchToSpace(spaceId: String)
}
@ -97,7 +99,9 @@ class MatrixToBottomSheet :
viewModel.observeViewEvents {
when (it) {
is MatrixToViewEvents.NavigateToRoom -> {
interactionListener?.mxToBottomSheetNavigateToRoom(it.roomId)
withState(viewModel) { state ->
interactionListener?.mxToBottomSheetNavigateToRoom(it.roomId, state.origin.toViewRoomTrigger())
}
dismiss()
}
MatrixToViewEvents.Dismiss -> dismiss()
@ -116,9 +120,9 @@ class MatrixToBottomSheet :
}
companion object {
fun withLink(matrixToLink: String): MatrixToBottomSheet {
fun withLink(matrixToLink: String, origin: OriginOfMatrixTo): MatrixToBottomSheet {
return MatrixToBottomSheet().apply {
setArguments(MatrixToArgs(matrixToLink = matrixToLink))
setArguments(MatrixToArgs(matrixToLink = matrixToLink, origin = origin))
}
}
}

View file

@ -30,12 +30,14 @@ data class MatrixToBottomSheetState(
val matrixItem: Async<MatrixItem> = Uninitialized,
val startChattingState: Async<Unit> = Uninitialized,
val roomPeekResult: Async<RoomInfoResult> = Uninitialized,
val peopleYouKnow: Async<List<MatrixItem.UserItem>> = Uninitialized
val peopleYouKnow: Async<List<MatrixItem.UserItem>> = Uninitialized,
val origin: OriginOfMatrixTo
) : MavericksState {
constructor(args: MatrixToBottomSheet.MatrixToArgs) : this(
deepLink = args.matrixToLink,
linkType = PermalinkParser.parse(args.matrixToLink)
linkType = PermalinkParser.parse(args.matrixToLink),
origin = args.origin
)
}

View file

@ -30,6 +30,8 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.createdirect.DirectRoomHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -37,6 +39,7 @@ import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.peeking.PeekResult
@ -50,7 +53,8 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
private val session: Session,
private val stringProvider: StringProvider,
private val directRoomHelper: DirectRoomHelper,
private val errorFormatter: ErrorFormatter
private val errorFormatter: ErrorFormatter,
private val analyticsTracker: AnalyticsTracker
) : VectorViewModel<MatrixToBottomSheetState, MatrixToAction, MatrixToViewEvents>(initialState) {
@AssistedFactory
@ -275,6 +279,11 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
val joinResult = session.spaceService().joinSpace(joinSpace.spaceID, null, joinSpace.viaServers?.take(3) ?: emptyList())
withState { state ->
session.getRoomSummary(joinSpace.spaceID)?.let { summary ->
analyticsTracker.capture(summary.toAnalyticsJoinedRoom(state.origin.toJoinedRoomTrigger()))
}
}
if (joinResult.isSuccess()) {
_viewEvents.post(MatrixToViewEvents.NavigateToSpace(joinSpace.spaceID))
} else {
@ -303,7 +312,14 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor(
reason = null,
viaServers = action.viaServers?.take(3) ?: emptyList()
)
_viewEvents.post(MatrixToViewEvents.NavigateToRoom(getRoomIdFromRoomIdOrAlias(action.roomIdOrAlias)))
val roomId = getRoomIdFromRoomIdOrAlias(action.roomIdOrAlias)
withState { state ->
session.getRoomSummary(roomId)?.let { summary ->
analyticsTracker.capture(summary.toAnalyticsJoinedRoom(state.origin.toJoinedRoomTrigger()))
}
}
_viewEvents.post(MatrixToViewEvents.NavigateToRoom(roomId))
} catch (failure: Throwable) {
_viewEvents.post(MatrixToViewEvents.ShowModalError(errorFormatter.toHumanReadable(failure)))
} finally {

View file

@ -0,0 +1,51 @@
/*
* 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.matrixto
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.analytics.plan.ViewRoom
enum class OriginOfMatrixTo {
LINK,
NOTIFICATION,
TIMELINE,
SPACE_EXPLORE,
ROOM_LIST,
USER_CODE
}
fun OriginOfMatrixTo.toJoinedRoomTrigger(): JoinedRoom.Trigger? {
return when (this) {
OriginOfMatrixTo.LINK -> JoinedRoom.Trigger.MobilePermalink
OriginOfMatrixTo.NOTIFICATION -> JoinedRoom.Trigger.Notification
OriginOfMatrixTo.TIMELINE -> JoinedRoom.Trigger.Timeline
OriginOfMatrixTo.SPACE_EXPLORE -> JoinedRoom.Trigger.SpaceHierarchy
OriginOfMatrixTo.ROOM_LIST -> JoinedRoom.Trigger.RoomDirectory
OriginOfMatrixTo.USER_CODE -> null
}
}
fun OriginOfMatrixTo.toViewRoomTrigger(): ViewRoom.Trigger? {
return when (this) {
OriginOfMatrixTo.LINK -> ViewRoom.Trigger.MobilePermalink
OriginOfMatrixTo.NOTIFICATION -> ViewRoom.Trigger.Notification
OriginOfMatrixTo.TIMELINE -> ViewRoom.Trigger.Timeline
OriginOfMatrixTo.SPACE_EXPLORE -> ViewRoom.Trigger.SpaceHierarchy
OriginOfMatrixTo.ROOM_LIST -> ViewRoom.Trigger.RoomDirectory
OriginOfMatrixTo.USER_CODE -> null
}
}

View file

@ -39,6 +39,9 @@ import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.toast
import im.vector.app.features.VectorFeatures
import im.vector.app.features.VectorFeatures.OnboardingVariant
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsViewRoom
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity
import im.vector.app.features.call.conference.JitsiCallViewModel
import im.vector.app.features.call.conference.VectorJitsiActivity
@ -68,6 +71,7 @@ import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.login.LoginActivity
import im.vector.app.features.login.LoginConfig
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.media.AttachmentData
import im.vector.app.features.media.BigImageViewerActivity
import im.vector.app.features.media.VectorAttachmentViewerActivity
@ -118,7 +122,8 @@ class DefaultNavigator @Inject constructor(
private val widgetArgsBuilder: WidgetArgsBuilder,
private val appStateHandler: AppStateHandler,
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
private val features: VectorFeatures
private val features: VectorFeatures,
private val analyticsTracker: AnalyticsTracker
) : Navigator {
override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) {
@ -150,12 +155,23 @@ class DefaultNavigator @Inject constructor(
roomId: String,
eventId: String?,
buildTask: Boolean,
isInviteAlreadyAccepted: Boolean
isInviteAlreadyAccepted: Boolean,
trigger: ViewRoom.Trigger?
) {
if (sessionHolder.getSafeActiveSession()?.getRoom(roomId) == null) {
fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast())
return
}
trigger?.let {
analyticsTracker.capture(
sessionHolder.getActiveSession().getRoomSummary(roomId).toAnalyticsViewRoom(
trigger = trigger,
groupingMethod = appStateHandler.getCurrentRoomGroupingMethod()
)
)
}
val args = TimelineArgs(roomId = roomId, eventId = eventId, isInviteAlreadyAccepted = isInviteAlreadyAccepted)
val intent = RoomDetailActivity.newIntent(context, args)
startActivity(context, intent, buildTask)
@ -296,13 +312,13 @@ class DefaultNavigator @Inject constructor(
context.startActivity(intent)
}
override fun openMatrixToBottomSheet(context: Context, link: String) {
override fun openMatrixToBottomSheet(context: Context, link: String, origin: OriginOfMatrixTo) {
if (context is AppCompatActivity) {
if (context !is MatrixToBottomSheet.InteractionListener) {
fatalError("Caller context should implement MatrixToBottomSheet.InteractionListener", vectorPreferences.failFast())
}
// TODO check if there is already one??
MatrixToBottomSheet.withLink(link)
MatrixToBottomSheet.withLink(link, origin)
.show(context.supportFragmentManager, "HA#MatrixToBottomSheet")
}
}

View file

@ -23,12 +23,14 @@ import android.net.Uri
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.core.util.Pair
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import im.vector.app.features.location.LocationData
import im.vector.app.features.location.LocationSharingMode
import im.vector.app.features.login.LoginConfig
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.media.AttachmentData
import im.vector.app.features.pin.PinMode
import im.vector.app.features.poll.PollMode
@ -50,7 +52,12 @@ interface Navigator {
fun softLogout(context: Context)
fun openRoom(context: Context, roomId: String, eventId: String? = null, buildTask: Boolean = false, isInviteAlreadyAccepted: Boolean = false)
fun openRoom(context: Context,
roomId: String,
eventId: String? = null,
buildTask: Boolean = false,
isInviteAlreadyAccepted: Boolean = false,
trigger: ViewRoom.Trigger? = null)
sealed class PostSwitchSpaceAction {
object None : PostSwitchSpaceAction()
@ -79,7 +86,7 @@ interface Navigator {
fun openRoomPreview(context: Context, roomPreviewData: RoomPreviewData, fromEmailInviteLink: PermalinkData.RoomEmailInviteLink? = null)
fun openMatrixToBottomSheet(context: Context, link: String)
fun openMatrixToBottomSheet(context: Context, link: String, origin: OriginOfMatrixTo)
fun openCreateRoom(context: Context, initialName: String = "", openAfterCreate: Boolean = true)

View file

@ -25,6 +25,7 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.session.coroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
@ -85,7 +86,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
session.coroutineScope.launch {
tryOrNull {
session.roomService().joinRoom(room.roomId)
analyticsTracker.capture(room.roomSummary().toAnalyticsJoinedRoom())
analyticsTracker.capture(room.roomSummary().toAnalyticsJoinedRoom(JoinedRoom.Trigger.Notification))
}
}
}

View file

@ -25,6 +25,7 @@ import im.vector.app.core.extensions.isIgnored
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.core.utils.toast
import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData
import kotlinx.coroutines.Dispatchers
@ -192,12 +193,12 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
navigationInterceptor.openJoinedRoomScreen(buildTask, roomId, eventId, rawLink, context, rootThreadEventId, roomSummary)
} else {
// maybe open space preview navigator.openSpacePreview(context, roomId)? if already joined?
navigator.openMatrixToBottomSheet(context, rawLink.toString())
navigator.openMatrixToBottomSheet(context, rawLink.toString(), OriginOfMatrixTo.LINK)
}
}
else -> {
// XXX this could trigger another server load
navigator.openMatrixToBottomSheet(context, rawLink.toString())
navigator.openMatrixToBottomSheet(context, rawLink.toString(), OriginOfMatrixTo.LINK)
}
}
}

View file

@ -33,6 +33,7 @@ import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.utils.toast
import im.vector.app.databinding.FragmentPublicRoomsBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.permalink.NavigationInterceptor
import im.vector.app.features.permalink.PermalinkHandler
import kotlinx.coroutines.flow.debounce
@ -143,7 +144,11 @@ class PublicRoomsFragment @Inject constructor(
withState(viewModel) { state ->
when (joinState) {
JoinState.JOINED -> {
navigator.openRoom(requireActivity(), publicRoom.roomId)
navigator.openRoom(
context = requireActivity(),
roomId = publicRoom.roomId,
trigger = ViewRoom.Trigger.RoomDirectory
)
}
else -> {
// ROOM PREVIEW

View file

@ -29,6 +29,7 @@ import im.vector.app.core.extensions.popBackstack
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.createroom.CreateRoomArgs
@ -88,8 +89,8 @@ class RoomDirectoryActivity : VectorBaseActivity<ActivitySimpleBinding>(), Matri
}
}
override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId)
override fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?) {
navigator.openRoom(this, roomId, trigger = trigger)
}
override fun mxToBottomSheetSwitchToSpace(spaceId: String) {

View file

@ -29,6 +29,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
@ -226,7 +227,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
session.roomService().joinRoom(action.publicRoom.roomId, viaServers = viaServers)
analyticsTracker.capture(action.publicRoom.toAnalyticsJoinedRoom())
analyticsTracker.capture(action.publicRoom.toAnalyticsJoinedRoom(JoinedRoom.Trigger.RoomDirectory))
// We do not update the joiningRoomsIds here, because, the room is not joined yet regarding the sync data.
// Instead, we wait for the room to be joined
} catch (failure: Throwable) {

View file

@ -38,6 +38,7 @@ import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.ColorProvider
import im.vector.app.databinding.FragmentCreateRoomBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.RoomDirectorySharedAction
import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
@ -219,20 +220,25 @@ class CreateRoomFragment @Inject constructor(
val async = state.asyncCreateRoomRequest
views.waitingView.root.isVisible = async is Loading
if (async is Success) {
val roomId = async()
// Navigate to freshly created room
if (state.openAfterCreate) {
if (state.isSubSpace) {
navigator.switchToSpace(
requireContext(),
async(),
roomId,
Navigator.PostSwitchSpaceAction.None
)
} else {
navigator.openRoom(requireActivity(), async())
navigator.openRoom(
context = requireActivity(),
roomId = roomId,
trigger = ViewRoom.Trigger.Created
)
}
}
sharedActionViewModel.post(RoomDirectorySharedAction.CreateRoomSuccess(async()))
sharedActionViewModel.post(RoomDirectorySharedAction.CreateRoomSuccess(roomId))
sharedActionViewModel.post(RoomDirectorySharedAction.Close)
} else {
// Populate list with Epoxy

View file

@ -38,6 +38,7 @@ import im.vector.app.core.utils.styleMatchingText
import im.vector.app.core.utils.tappableMatchingText
import im.vector.app.databinding.FragmentRoomPreviewNoPreviewBinding
import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.JoinState
@ -100,7 +101,13 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
if (state.roomType == RoomType.SPACE) {
navigator.switchToSpace(requireActivity(), state.roomId, Navigator.PostSwitchSpaceAction.None)
} else {
navigator.openRoom(requireActivity(), state.roomId, roomPreviewData.eventId, roomPreviewData.buildTask)
navigator.openRoom(
context = requireActivity(),
roomId = state.roomId,
eventId = roomPreviewData.eventId,
buildTask = roomPreviewData.buildTask,
trigger = ViewRoom.Trigger.MobileRoomPreview
)
}
}

View file

@ -27,7 +27,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsRoomSize
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.roomdirectory.JoinState
import kotlinx.coroutines.Dispatchers
@ -37,6 +37,7 @@ import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.identity.SharedState
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
@ -248,17 +249,13 @@ class RoomPreviewViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
session.roomService().joinRoom(state.roomId, viaServers = state.homeServers)
analyticsTracker.capture(JoinedRoom(
// Always false in this case (?)
isDM = false,
isSpace = false,
roomSize = state.numJoinMembers.toAnalyticsRoomSize(),
))
// We do not update the joiningRoomsIds here, because, the room is not joined yet regarding the sync data.
// Instead, we wait for the room to be joined
} catch (failure: Throwable) {
setState { copy(lastError = failure) }
}
session.getRoomSummary(state.roomId)
?.let { analyticsTracker.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.RoomPreview)) }
}
}
}

View file

@ -37,6 +37,7 @@ import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentIncomingShareBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.attachments.AttachmentsHelper
import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity
import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs
@ -125,7 +126,11 @@ class IncomingShareFragment @Inject constructor(
private fun handleMultipleRoomsShareDone(viewEvent: IncomingShareViewEvents.MultipleRoomsShareDone) {
requireActivity().let {
navigator.openRoom(it, viewEvent.roomId)
navigator.openRoom(
context = it,
roomId = viewEvent.roomId,
trigger = ViewRoom.Trigger.MobileLinkShare
)
it.finish()
}
}

View file

@ -30,7 +30,9 @@ import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
import im.vector.app.features.spaces.explore.SpaceDirectoryArgs
@ -92,10 +94,14 @@ class SpaceExploreActivity : VectorBaseActivity<ActivitySimpleBinding>(), Matrix
finish()
}
is SpaceDirectoryViewEvents.NavigateToRoom -> {
navigator.openRoom(this, it.roomId)
navigator.openRoom(
context = this,
roomId = it.roomId,
trigger = ViewRoom.Trigger.SpaceHierarchy
)
}
is SpaceDirectoryViewEvents.NavigateToMxToBottomSheet -> {
MatrixToBottomSheet.withLink(it.link).show(supportFragmentManager, "ShowChild")
MatrixToBottomSheet.withLink(it.link, OriginOfMatrixTo.SPACE_EXPLORE).show(supportFragmentManager, "ShowChild")
}
is SpaceDirectoryViewEvents.NavigateToCreateNewRoom -> {
createRoomResultLauncher.launch(CreateRoomActivity.getIntent(
@ -121,8 +127,8 @@ class SpaceExploreActivity : VectorBaseActivity<ActivitySimpleBinding>(), Matrix
}
}
override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId)
override fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?) {
navigator.openRoom(this, roomId, trigger = trigger)
}
override fun mxToBottomSheetSwitchToSpace(spaceId: String) {

View file

@ -27,6 +27,9 @@ import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
@ -49,7 +52,8 @@ import timber.log.Timber
class SpaceDirectoryViewModel @AssistedInject constructor(
@Assisted val initialState: SpaceDirectoryState,
private val session: Session
private val session: Session,
private val analyticsTracker: AnalyticsTracker
) : VectorViewModel<SpaceDirectoryState, SpaceDirectoryViewAction, SpaceDirectoryViewEvents>(initialState) {
@AssistedFactory
@ -416,6 +420,9 @@ class SpaceDirectoryViewModel @AssistedInject constructor(
} catch (failure: Throwable) {
Timber.e(failure, "## Space: Failed to join room or subspace")
}
session.getRoomSummary(childId)
?.let { analyticsTracker.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.SpaceHierarchy)) }
}
}
}

View file

@ -30,6 +30,7 @@ import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.GenericIdArgs
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleLoadingBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -90,7 +91,11 @@ class SpacePeopleActivity : VectorBaseActivity<ActivitySimpleLoadingBinding>() {
}
private fun navigateToRooms(action: SpacePeopleSharedAction.NavigateToRoom) {
navigator.openRoom(this, action.roomId)
navigator.openRoom(
context = this,
roomId = action.roomId,
trigger = ViewRoom.Trigger.MobileSpaceMembers
)
finish()
}

View file

@ -34,7 +34,9 @@ import im.vector.app.core.extensions.replaceFragment
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.onPermissionDeniedSnackbar
import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.matrixto.MatrixToBottomSheet
import im.vector.app.features.matrixto.OriginOfMatrixTo
import im.vector.app.features.qrcode.QrCodeScannerEvents
import im.vector.app.features.qrcode.QrCodeScannerFragment
import im.vector.app.features.qrcode.QrCodeScannerViewModel
@ -92,7 +94,7 @@ class UserCodeActivity : VectorBaseActivity<ActivitySimpleBinding>(),
}
is UserCodeState.Mode.RESULT -> {
showFragment(ShowUserCodeFragment::class)
MatrixToBottomSheet.withLink(mode.rawLink).show(supportFragmentManager, "MatrixToBottomSheet")
MatrixToBottomSheet.withLink(mode.rawLink, OriginOfMatrixTo.USER_CODE).show(supportFragmentManager, "MatrixToBottomSheet")
}
}
}
@ -141,8 +143,8 @@ class UserCodeActivity : VectorBaseActivity<ActivitySimpleBinding>(),
}
}
override fun mxToBottomSheetNavigateToRoom(roomId: String) {
navigator.openRoom(this, roomId)
override fun mxToBottomSheetNavigateToRoom(roomId: String, trigger: ViewRoom.Trigger?) {
navigator.openRoom(this, roomId, trigger = trigger)
}
override fun mxToBottomSheetSwitchToSpace(spaceId: String) {}