mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-796 | Added library analytics (#2995)
DROID-796 Library | Enhancement | Added library analytics
This commit is contained in:
parent
c8cabb84c1
commit
9a68347cbe
11 changed files with 122 additions and 25 deletions
|
@ -115,12 +115,18 @@ object EventsDictionary {
|
|||
const val goBack = "HistoryBack"
|
||||
const val bookmarkOpenUrl = "BlockBookmarkOpenUrl"
|
||||
|
||||
//Toolbars
|
||||
// Toolbars
|
||||
const val slashMenu = "KeyboardBarSlashMenu"
|
||||
const val styleMenu = "KeyboardBarStyleMenu"
|
||||
const val selectionMenu = "KeyboardBarSelectionMenu"
|
||||
const val mentionMenu = "KeyboardBarMentionMenu"
|
||||
|
||||
// Library
|
||||
const val libraryView = "LibraryView"
|
||||
const val libraryScreenType = "ScreenType"
|
||||
const val libraryScreenRelation = "ScreenRelation"
|
||||
const val librarySetTypeName = "SetTypeName"
|
||||
const val libraryCreateType = "CreateType"
|
||||
|
||||
// Routes
|
||||
object Routes {
|
||||
|
|
|
@ -41,6 +41,7 @@ class AmplitudeTracker(
|
|||
renderTime = event.duration?.render
|
||||
)
|
||||
tracker.logEvent(event.name, props)
|
||||
Timber.d("Analytics Amplitude(event = $event)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.di.feature.library
|
|||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
|
@ -193,4 +194,6 @@ interface LibraryDependencies : ComponentDependencies {
|
|||
fun channel(): SubscriptionEventChannel
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun userSettingsRepository(): UserSettingsRepository
|
||||
|
||||
fun analytics(): Analytics
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.anytypeio.anytype.di.feature.types
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
|
@ -65,4 +66,5 @@ interface TypeCreationDependencies : ComponentDependencies {
|
|||
fun blockRepository(): BlockRepository
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun urlBuilder(): UrlBuilder
|
||||
fun analytics(): Analytics
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.anytypeio.anytype.di.feature.types
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
@ -71,4 +71,5 @@ object TypeEditModule {
|
|||
interface TypeEditDependencies : ComponentDependencies {
|
||||
fun blockRepository(): BlockRepository
|
||||
fun urlBuilder(): UrlBuilder
|
||||
fun analytics(): Analytics
|
||||
}
|
|
@ -21,6 +21,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.presentation.library.LibraryEvent
|
||||
import com.anytypeio.anytype.ui.library.LibraryConfiguration
|
||||
import com.anytypeio.anytype.ui.library.LibraryScreenConfig
|
||||
import com.anytypeio.anytype.ui.library.ScreenState
|
||||
|
@ -36,7 +37,7 @@ fun LibraryTabs(
|
|||
modifier: Modifier,
|
||||
pagerState: PagerState,
|
||||
configuration: LibraryConfiguration,
|
||||
screenState: MutableState<ScreenState>,
|
||||
screenState: MutableState<ScreenState>
|
||||
) = WrapWithLibraryAnimation(visible = screenState.value.visible()) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
|
|
|
@ -87,8 +87,22 @@ fun LibraryListTabsContent(
|
|||
userScrollEnabled = screenState.value == ScreenState.CONTENT
|
||||
) { index ->
|
||||
val data = when (configuration[index]) {
|
||||
is LibraryListConfig.Types, is LibraryListConfig.Relations -> tabs.my
|
||||
is LibraryListConfig.TypesLibrary, is LibraryListConfig.RelationsLibrary -> tabs.lib
|
||||
is LibraryListConfig.Types -> {
|
||||
vmEventStream.invoke(LibraryEvent.Ui.ViewTypes)
|
||||
tabs.my
|
||||
}
|
||||
is LibraryListConfig.Relations -> {
|
||||
vmEventStream.invoke(LibraryEvent.Ui.ViewRelations)
|
||||
tabs.my
|
||||
}
|
||||
is LibraryListConfig.TypesLibrary -> {
|
||||
vmEventStream.invoke(LibraryEvent.Ui.ViewLibTypes)
|
||||
tabs.lib
|
||||
}
|
||||
is LibraryListConfig.RelationsLibrary -> {
|
||||
vmEventStream.invoke(LibraryEvent.Ui.ViewLibRelations)
|
||||
tabs.lib
|
||||
}
|
||||
}
|
||||
val itemsListState = rememberLazyListState()
|
||||
Column(
|
||||
|
|
|
@ -4,8 +4,8 @@ sealed class LibraryEvent {
|
|||
|
||||
sealed class BottomMenu : LibraryEvent() {
|
||||
class Back : BottomMenu()
|
||||
class Search: BottomMenu()
|
||||
class AddDoc: BottomMenu()
|
||||
class Search : BottomMenu()
|
||||
class AddDoc : BottomMenu()
|
||||
}
|
||||
|
||||
sealed class Query(open val query: String) : LibraryEvent() {
|
||||
|
@ -20,14 +20,26 @@ sealed class LibraryEvent {
|
|||
class Relation(override val item: LibraryView) : ToggleInstall(item)
|
||||
}
|
||||
|
||||
sealed class Type: LibraryEvent() {
|
||||
sealed class Type : LibraryEvent() {
|
||||
class Create(val name: String = "") : Type()
|
||||
class Edit(val item: LibraryView.MyTypeView) : Type()
|
||||
}
|
||||
|
||||
sealed class Relation: LibraryEvent() {
|
||||
sealed class Relation : LibraryEvent() {
|
||||
class Create(val name: String = "") : Relation()
|
||||
class Edit(val item: LibraryView.MyRelationView) : Relation()
|
||||
}
|
||||
|
||||
}
|
||||
sealed class Ui(val type: String, val view: String) : LibraryEvent() {
|
||||
object ViewTypes : Ui(type = TypeType, view = ViewYour)
|
||||
object ViewRelations : Ui(type = TypeRelation, view = ViewYour)
|
||||
object ViewLibTypes : Ui(type = TypeType, view = ViewLibrary)
|
||||
object ViewLibRelations : Ui(type = TypeRelation, view = ViewLibrary)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const val TypeType = "type"
|
||||
private const val TypeRelation = "relation"
|
||||
private const val ViewYour = "your"
|
||||
private const val ViewLibrary = "library"
|
|
@ -3,6 +3,12 @@ package com.anytypeio.anytype.presentation.library
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryScreenRelation
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryScreenType
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryView
|
||||
import com.anytypeio.anytype.analytics.base.sendEvent
|
||||
import com.anytypeio.anytype.analytics.props.Props
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_utils.ext.orNull
|
||||
|
@ -34,7 +40,8 @@ class LibraryViewModel(
|
|||
private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace,
|
||||
private val resourceManager: LibraryResourceManager,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val createObject: CreateObject
|
||||
private val createObject: CreateObject,
|
||||
private val analytics: Analytics
|
||||
) : NavigationViewModel<LibraryViewModel.Navigation>() {
|
||||
|
||||
private val uiEvents = MutableStateFlow<LibraryEvent>(LibraryEvent.Query.MyTypes(""))
|
||||
|
@ -86,11 +93,25 @@ class LibraryViewModel(
|
|||
is LibraryEvent.Type -> proceedWithTypeActions(it)
|
||||
is LibraryEvent.Relation -> proceedWithRelationActions(it)
|
||||
is LibraryEvent.BottomMenu -> proceedWithBottomMenuActions(it)
|
||||
is LibraryEvent.Ui -> proceedWithViewAnalytics(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithViewAnalytics(it: LibraryEvent.Ui) {
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = libraryView,
|
||||
props = Props(
|
||||
mapOf(
|
||||
"type" to it.type,
|
||||
"view" to it.view
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun proceedWithBottomMenuActions(it: LibraryEvent.BottomMenu) {
|
||||
when (it) {
|
||||
is LibraryEvent.BottomMenu.Back -> navigate(Navigation.Back())
|
||||
|
@ -104,7 +125,7 @@ class LibraryViewModel(
|
|||
createObject.execute(CreateObject.Param(type = null))
|
||||
.fold(
|
||||
onSuccess = { result ->
|
||||
navigate(Navigation.CreateDoc(result.objectId))
|
||||
navigate(Navigation.CreateDoc(result.objectId))
|
||||
},
|
||||
onFailure = { e -> Timber.e(e, "Error while creating a new page") }
|
||||
)
|
||||
|
@ -137,15 +158,35 @@ class LibraryViewModel(
|
|||
|
||||
private fun proceedWithTypeActions(event: LibraryEvent.Type) {
|
||||
when (event) {
|
||||
is LibraryEvent.Type.Create -> navigate(Navigation.OpenTypeCreation(event.name))
|
||||
is LibraryEvent.Type.Edit -> navigate(Navigation.OpenTypeEditing(event.item))
|
||||
is LibraryEvent.Type.Create -> {
|
||||
navigate(Navigation.OpenTypeCreation(event.name))
|
||||
}
|
||||
is LibraryEvent.Type.Edit -> {
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = libraryScreenType,
|
||||
props = Props(
|
||||
map = mapOf("objectType" to event.item.id)
|
||||
)
|
||||
)
|
||||
navigate(Navigation.OpenTypeEditing(event.item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithRelationActions(event: LibraryEvent.Relation) {
|
||||
when (event) {
|
||||
is LibraryEvent.Relation.Create -> navigate(Navigation.OpenRelationCreation(event.name))
|
||||
is LibraryEvent.Relation.Edit -> navigate(Navigation.OpenRelationEditing(event.item))
|
||||
is LibraryEvent.Relation.Edit -> {
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = libraryScreenRelation,
|
||||
props = Props(
|
||||
map = mapOf("relationKey" to event.item.id)
|
||||
)
|
||||
)
|
||||
navigate(Navigation.OpenRelationEditing(event.item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +349,8 @@ class LibraryViewModel(
|
|||
private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace,
|
||||
private val resourceManager: LibraryResourceManager,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val createObject: CreateObject
|
||||
private val createObject: CreateObject,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
@ -321,7 +363,8 @@ class LibraryViewModel(
|
|||
removeObjectsFromWorkspace,
|
||||
resourceManager,
|
||||
setObjectDetails,
|
||||
createObject
|
||||
createObject,
|
||||
analytics
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
@ -345,9 +388,9 @@ class LibraryViewModel(
|
|||
|
||||
class Back : Navigation()
|
||||
|
||||
class Search: Navigation()
|
||||
class Search : Navigation()
|
||||
|
||||
class CreateDoc(val id: Id): Navigation()
|
||||
class CreateDoc(val id: Id) : Navigation()
|
||||
}
|
||||
|
||||
sealed class Effect {
|
||||
|
|
|
@ -3,6 +3,9 @@ package com.anytypeio.anytype.presentation.types
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryCreateType
|
||||
import com.anytypeio.anytype.analytics.base.sendEvent
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -26,7 +29,8 @@ import timber.log.Timber
|
|||
class TypeCreationViewModel(
|
||||
private val createTypeInteractor: CreateType,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val emojiProvider: EmojiProvider
|
||||
private val emojiProvider: EmojiProvider,
|
||||
private val analytics: Analytics
|
||||
) : NavigationViewModel<TypeCreationViewModel.Navigation>() {
|
||||
|
||||
private val unicodeIconFlow = MutableStateFlow("")
|
||||
|
@ -59,6 +63,7 @@ class TypeCreationViewModel(
|
|||
)
|
||||
).fold(
|
||||
onSuccess = {
|
||||
viewModelScope.sendEvent(analytics = analytics, eventName = libraryCreateType)
|
||||
navigate(Navigation.BackWithCreatedType)
|
||||
},
|
||||
onFailure = {
|
||||
|
@ -96,14 +101,16 @@ class TypeCreationViewModel(
|
|||
class Factory @Inject constructor(
|
||||
private val createType: CreateType,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val emojiProvider: EmojiProvider
|
||||
private val emojiProvider: EmojiProvider,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return TypeCreationViewModel(
|
||||
createTypeInteractor = createType,
|
||||
urlBuilder = urlBuilder,
|
||||
emojiProvider = emojiProvider
|
||||
emojiProvider = emojiProvider,
|
||||
analytics = analytics
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package com.anytypeio.anytype.presentation.types
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.librarySetTypeName
|
||||
import com.anytypeio.anytype.analytics.base.sendEvent
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -23,7 +26,8 @@ class TypeEditViewModel(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
private val id: Id,
|
||||
private val name: String,
|
||||
private val icon: String
|
||||
private val icon: String,
|
||||
private val analytics: Analytics
|
||||
) : NavigationViewModel<TypeEditViewModel.Navigation>() {
|
||||
|
||||
private val unicodeIconFlow = MutableStateFlow(icon)
|
||||
|
@ -68,6 +72,7 @@ class TypeEditViewModel(
|
|||
}
|
||||
|
||||
fun updateObjectDetails(name: String) {
|
||||
viewModelScope.sendEvent(analytics = analytics, eventName = librarySetTypeName)
|
||||
navigate(Navigation.BackWithModify(id, name, unicodeIconFlow.value))
|
||||
}
|
||||
|
||||
|
@ -86,7 +91,8 @@ class TypeEditViewModel(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
@TypeId private val id: Id,
|
||||
@TypeName private val name: String,
|
||||
@TypeIcon private val icon: String
|
||||
@TypeIcon private val icon: String,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
@ -94,7 +100,8 @@ class TypeEditViewModel(
|
|||
urlBuilder = urlBuilder,
|
||||
id = id,
|
||||
name = name,
|
||||
icon = icon
|
||||
icon = icon,
|
||||
analytics = analytics
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue