mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Add location related analytics (#1241)
* Refactor trackComposer method * Track location screen * Refactor isPinDropSharing -> isSharingUserLocation * Add trackComposer event * Fix UTs * Cleanup * Add AnalyticsLocationType
This commit is contained in:
@@ -511,15 +511,21 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
coordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .selectedLocation(let geoURI):
|
||||
case .selectedLocation(let geoURI, let isUserLocation):
|
||||
Task {
|
||||
_ = await self.roomProxy?.sendLocation(body: geoURI.bodyMessage,
|
||||
geoURI: geoURI,
|
||||
description: nil,
|
||||
zoomLevel: nil,
|
||||
assetType: .pin)
|
||||
assetType: isUserLocation ? .sender : .pin)
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
self.analytics.trackComposer(inThread: false,
|
||||
isEditing: false,
|
||||
isReply: false,
|
||||
locationType: isUserLocation ? .myLocation : .pin,
|
||||
startsThread: nil)
|
||||
case .close:
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ enum LocationSharingViewError: Error, Hashable {
|
||||
|
||||
enum StaticLocationScreenViewModelAction {
|
||||
case close
|
||||
case sendLocation(GeoURI)
|
||||
case sendLocation(GeoURI, isUserLocation: Bool)
|
||||
}
|
||||
|
||||
enum StaticLocationInteractionMode: Hashable {
|
||||
@@ -33,9 +33,9 @@ enum StaticLocationInteractionMode: Hashable {
|
||||
}
|
||||
|
||||
struct StaticLocationScreenViewState: BindableState {
|
||||
init(interactionMode: StaticLocationInteractionMode, isPinDropSharing: Bool = true, showsUserLocationMode: ShowUserLocationMode = .hide) {
|
||||
init(interactionMode: StaticLocationInteractionMode, isSharingUserLocation: Bool = false, showsUserLocationMode: ShowUserLocationMode = .hide) {
|
||||
self.interactionMode = interactionMode
|
||||
self.isPinDropSharing = isPinDropSharing
|
||||
self.isSharingUserLocation = isSharingUserLocation
|
||||
self.showsUserLocationMode = showsUserLocationMode
|
||||
|
||||
switch interactionMode {
|
||||
@@ -47,10 +47,10 @@ struct StaticLocationScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
let interactionMode: StaticLocationInteractionMode
|
||||
/// Indicates whether the user has moved around the map to drop a pin somewhere other than their current location
|
||||
var isPinDropSharing = true
|
||||
/// Indicates whether the user is sharing his current location
|
||||
var isSharingUserLocation: Bool
|
||||
/// Behavior mode of the current user's location, can be hidden, only shown and shown following the user
|
||||
var showsUserLocationMode: ShowUserLocationMode = .hide
|
||||
var showsUserLocationMode: ShowUserLocationMode
|
||||
|
||||
var bindings = StaticLocationScreenBindings()
|
||||
|
||||
@@ -67,10 +67,10 @@ struct StaticLocationScreenViewState: BindableState {
|
||||
}
|
||||
}
|
||||
|
||||
var showPinInTheCenter: Bool {
|
||||
var isLocationPickerMode: Bool {
|
||||
switch interactionMode {
|
||||
case .picker:
|
||||
return isPinDropSharing
|
||||
return true
|
||||
case .viewOnly:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ struct StaticLocationScreenCoordinatorParameters {
|
||||
|
||||
enum StaticLocationScreenCoordinatorAction {
|
||||
case close
|
||||
case selectedLocation(GeoURI)
|
||||
case selectedLocation(GeoURI, isUserLocation: Bool)
|
||||
}
|
||||
|
||||
final class StaticLocationScreenCoordinator: CoordinatorProtocol {
|
||||
@@ -51,8 +51,8 @@ final class StaticLocationScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .close:
|
||||
actionsSubject.send(.close)
|
||||
case .sendLocation(let geoURI):
|
||||
actionsSubject.send(.selectedLocation(geoURI))
|
||||
case .sendLocation(let geoURI, let isUserLocation):
|
||||
actionsSubject.send(.selectedLocation(geoURI, isUserLocation: isUserLocation))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -36,10 +36,10 @@ class StaticLocationScreenViewModel: StaticLocationScreenViewModelType, StaticLo
|
||||
actionsSubject.send(.close)
|
||||
case .selectLocation:
|
||||
guard let coordinate = state.bindings.mapCenterLocation else { return }
|
||||
actionsSubject.send(.sendLocation(.init(coordinate: coordinate)))
|
||||
actionsSubject.send(.sendLocation(.init(coordinate: coordinate), isUserLocation: state.isSharingUserLocation))
|
||||
case .userDidPan:
|
||||
state.showsUserLocationMode = .hide
|
||||
state.isPinDropSharing = true
|
||||
state.isSharingUserLocation = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ struct StaticLocationScreen: View {
|
||||
}
|
||||
mapView
|
||||
}
|
||||
.track(screen: context.viewState.isLocationPickerMode ? .locationSend : .locationView)
|
||||
.navigationTitle(context.viewState.navigationTitle)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
@@ -49,7 +50,7 @@ struct StaticLocationScreen: View {
|
||||
userDidPan: {
|
||||
context.send(viewAction: .userDidPan)
|
||||
})
|
||||
if context.viewState.showPinInTheCenter {
|
||||
if context.viewState.isLocationPickerMode {
|
||||
LocationMarkerView()
|
||||
}
|
||||
}
|
||||
@@ -105,7 +106,7 @@ struct StaticLocationScreen: View {
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: shareMarkerSize, height: shareMarkerSize)
|
||||
Text(context.viewState.isPinDropSharing ? L10n.screenShareThisLocationAction : L10n.screenShareMyLocationAction)
|
||||
Text(context.viewState.isSharingUserLocation ? L10n.screenShareMyLocationAction : L10n.screenShareThisLocationAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright 2023 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.
|
||||
//
|
||||
|
||||
import AnalyticsEvents
|
||||
|
||||
enum AnalyticsLocationType {
|
||||
case myLocation
|
||||
case pin
|
||||
}
|
||||
|
||||
extension AnalyticsEvent.Composer.LocationType {
|
||||
init(_ analyticsLocationType: AnalyticsLocationType) {
|
||||
switch analyticsLocationType {
|
||||
case .myLocation:
|
||||
self = .MyLocation
|
||||
case .pin:
|
||||
self = .PinDrop
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,8 @@ enum AnalyticsScreen: Int {
|
||||
case spaceBottomSheet
|
||||
case invites
|
||||
case createSpace
|
||||
case locationSend
|
||||
case locationView
|
||||
|
||||
/// The screen name reported to the AnalyticsEvent.
|
||||
var screenName: AnalyticsEvent.MobileScreen.ScreenName {
|
||||
@@ -145,6 +147,10 @@ enum AnalyticsScreen: Int {
|
||||
return .Invites
|
||||
case .createSpace:
|
||||
return .CreateSpace
|
||||
case .locationSend:
|
||||
return .LocationSend
|
||||
case .locationView:
|
||||
return .LocationView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,9 +141,19 @@ extension AnalyticsService {
|
||||
/// - inThread: whether the composer is used in a Thread
|
||||
/// - isEditing: whether the composer is used to edit a message
|
||||
/// - isReply: whether the composer is used to reply a message
|
||||
/// - locationType: the type of the shared location
|
||||
/// - startsThread: whether the composer is used to start a new thread
|
||||
func trackComposer(inThread: Bool, isEditing: Bool, isReply: Bool, startsThread: Bool?) {
|
||||
capture(event: AnalyticsEvent.Composer(inThread: inThread, isEditing: isEditing, isReply: isReply, startsThread: startsThread))
|
||||
func trackComposer(inThread: Bool,
|
||||
isEditing: Bool,
|
||||
isReply: Bool,
|
||||
locationType: AnalyticsLocationType? = nil,
|
||||
startsThread: Bool?) {
|
||||
capture(event: AnalyticsEvent.Composer(inThread: inThread,
|
||||
isEditing: isEditing,
|
||||
isLocation: locationType != nil,
|
||||
isReply: isReply,
|
||||
locationType: locationType.map { .init($0) },
|
||||
startsThread: startsThread))
|
||||
}
|
||||
|
||||
/// Track the presentation of a room
|
||||
|
||||
Reference in New Issue
Block a user