From 7d6da285358647e4bbaabab4df9ade9ea4533059 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 00:14:35 +0530 Subject: [PATCH 01/13] change max zoom to 10 --- app/build.gradle.kts | 11 ++--------- .../src/main/java/com/kafka/reader/pdf/PdfViewer.kt | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8d040817f..e890ebf9c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ android { defaultConfig { applicationId = "com.kafka.user" - versionCode = 58 - versionName = "0.18.0" + versionCode = 59 + versionName = "0.19.0" val properties = Properties() properties.load(project.rootProject.file("local.properties").inputStream()) @@ -113,13 +113,6 @@ android { checkDependencies = true warning += "AutoboxingStateCreation" } - - dependenciesInfo { - // Disables dependency metadata when building APKs. - includeInApk = false - // Disables dependency metadata when building Android App Bundles. - includeInBundle = false - } } dependencies { diff --git a/ui/reader/src/main/java/com/kafka/reader/pdf/PdfViewer.kt b/ui/reader/src/main/java/com/kafka/reader/pdf/PdfViewer.kt index cba0a6f80..b1f0779b9 100644 --- a/ui/reader/src/main/java/com/kafka/reader/pdf/PdfViewer.kt +++ b/ui/reader/src/main/java/com/kafka/reader/pdf/PdfViewer.kt @@ -33,4 +33,4 @@ data class PdfState( val onPageChange: (Int) -> Unit = { _ -> } ) -const val MaxZoom = 6f +const val MaxZoom = 10f From 84f70cc52ee63bb9b43d9689f5a642059a3e21c0 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 11:18:02 +0530 Subject: [PATCH 02/13] make downloads optional --- data/models/src/main/java/com/kafka/data/model/item/Doc.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/models/src/main/java/com/kafka/data/model/item/Doc.kt b/data/models/src/main/java/com/kafka/data/model/item/Doc.kt index 76c57dcd7..9b71e3c58 100644 --- a/data/models/src/main/java/com/kafka/data/model/item/Doc.kt +++ b/data/models/src/main/java/com/kafka/data/model/item/Doc.kt @@ -19,7 +19,7 @@ data class Doc( @Serializable(with = StringListSerializer::class) val description: List? = null, @SerialName("downloads") - val downloads: Int, + val downloads: Int = 0, @SerialName("format") @Serializable(with = StringListSerializer::class) val format: List? = null, From 0a9242bcae6940d3a2579a8d2e249d3025164246 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 22:16:01 +0530 Subject: [PATCH 03/13] Add Related Content feature - show related content from recommendation service on ite detail --- .../remote/config/RemoteConfigExtensions.kt | 3 + .../RecommendationRepository.kt | 7 +- .../RelatedContentRequestBody.kt | 30 +++++++ .../network/RecommendationService.kt | 7 ++ .../recommendation/GetRecommendedContent.kt | 2 +- .../recommendation/GetRelatedContent.kt | 42 +++++++++ .../components/{Components.kt => Labels.kt} | 2 +- .../java/org/kafka/item/detail/ItemDetail.kt | 90 ++++++++++++------- .../kafka/item/detail/ItemDetailViewModel.kt | 32 +++++-- .../kafka/item/detail/ItemDetailViewState.kt | 3 + .../detail/description/DescriptionDialog.kt | 19 +++- ui/item/src/main/res/values/strings.xml | 1 + 12 files changed, 195 insertions(+), 43 deletions(-) create mode 100644 data/repo/src/main/java/com/kafka/data/feature/recommendation/RelatedContentRequestBody.kt create mode 100644 domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRelatedContent.kt rename ui/components/src/main/java/org/kafka/ui/components/{Components.kt => Labels.kt} (100%) diff --git a/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt b/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt index a190dfe36..7663c48f2 100644 --- a/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt +++ b/core/remote-config/src/main/java/com/kafka/remote/config/RemoteConfigExtensions.kt @@ -9,6 +9,7 @@ const val VIEW_RECOMMENDATION_ENABLED = "view_recommendation_data_enabled" const val USE_RECOMMENDATION_ENABLED = "use_recommendation_data_enabled" const val RECOMMENDATION_ROW_ENABLED = "recommendation_row_enabled" const val RECOMMENDATION_ROW_INDEX = "recommendation_row_index" +const val RELATED_CONTENT_ROW_ENABLED = "related_content_row_enabled" const val ONLINE_READER_ENABLED = "online_reader_enabled" const val EXACT_ALARM_ENABLED = "exact_alarm_enabled" @@ -30,6 +31,8 @@ fun RemoteConfig.isRecommendationRowEnabled() = getBoolean(RECOMMENDATION_ROW_EN fun RemoteConfig.recommendationRowIndex() = getLong(RECOMMENDATION_ROW_INDEX) +fun RemoteConfig.isRelatedContentRowEnabled() = getBoolean(RELATED_CONTENT_ROW_ENABLED) + fun RemoteConfig.isOnlineReaderEnabled() = getBoolean(ONLINE_READER_ENABLED) fun RemoteConfig.isExactAlarmEnabled() = getBoolean(EXACT_ALARM_ENABLED) diff --git a/data/repo/src/main/java/com/kafka/data/feature/recommendation/RecommendationRepository.kt b/data/repo/src/main/java/com/kafka/data/feature/recommendation/RecommendationRepository.kt index f6d2ea986..df8220900 100644 --- a/data/repo/src/main/java/com/kafka/data/feature/recommendation/RecommendationRepository.kt +++ b/data/repo/src/main/java/com/kafka/data/feature/recommendation/RecommendationRepository.kt @@ -20,11 +20,16 @@ class RecommendationRepository @Inject constructor( private val dispatchers: CoroutineDispatchers ) { - suspend fun getRecommendations(userId: String) = resultApiCall(dispatchers.io) { + suspend fun getRecommendedContent(userId: String) = resultApiCall(dispatchers.io) { val requestBody = ContentRecommendationRequestBody.fromUser(userId) recommendationService.getRecommendedContent(pipelessAppId, requestBody) } + suspend fun getRelatedContent(contentId: String) = resultApiCall(dispatchers.io) { + val requestBody = RelatedContentRequestBody.fromContent(contentId) + recommendationService.getRelatedContent(pipelessAppId, requestBody) + } + suspend fun postEvent( recommendationObjectFrom: RecommendationObject, recommendationRelationship: RecommendationRelationship, diff --git a/data/repo/src/main/java/com/kafka/data/feature/recommendation/RelatedContentRequestBody.kt b/data/repo/src/main/java/com/kafka/data/feature/recommendation/RelatedContentRequestBody.kt new file mode 100644 index 000000000..f40c036c4 --- /dev/null +++ b/data/repo/src/main/java/com/kafka/data/feature/recommendation/RelatedContentRequestBody.kt @@ -0,0 +1,30 @@ +package com.kafka.data.feature.recommendation + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RelatedContentRequestBody( + @SerialName("content_tagged_relationship_type") + val contentTaggedRelationshipType: String, + @SerialName("object") + val objectX: Object, + @SerialName("positive_rel") + val primaryPositiveRelationshipType: String +) { + @Serializable + data class Object( + @SerialName("id") + val id: String, + @SerialName("type") + val type: String + ) + + companion object { + fun fromContent(contentId: String) = RelatedContentRequestBody( + primaryPositiveRelationshipType = "viewed", + contentTaggedRelationshipType = "taggedWith", + objectX = Object(id = contentId, type = "content") + ) + } +} diff --git a/data/repo/src/main/java/com/kafka/data/feature/recommendation/network/RecommendationService.kt b/data/repo/src/main/java/com/kafka/data/feature/recommendation/network/RecommendationService.kt index 2ceacdfb9..ce5077d01 100644 --- a/data/repo/src/main/java/com/kafka/data/feature/recommendation/network/RecommendationService.kt +++ b/data/repo/src/main/java/com/kafka/data/feature/recommendation/network/RecommendationService.kt @@ -2,6 +2,7 @@ package com.kafka.data.feature.recommendation.network import com.kafka.data.feature.recommendation.ContentRecommendationRequestBody import com.kafka.data.feature.recommendation.RecommendedContentResponse +import com.kafka.data.feature.recommendation.RelatedContentRequestBody import com.kafka.data.model.recommendation.RecommendationRequestBody import okhttp3.ResponseBody import retrofit2.http.Body @@ -20,4 +21,10 @@ interface RecommendationService { @Path("app_id") appId: Int, @Body body: ContentRecommendationRequestBody, ): RecommendedContentResponse + + @POST("apps/{app_id}/algos/recommendations/related-content") + suspend fun getRelatedContent( + @Path("app_id") appId: Int, + @Body body: RelatedContentRequestBody, + ): RecommendedContentResponse } diff --git a/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRecommendedContent.kt b/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRecommendedContent.kt index d3326981a..5ba1ffdc4 100644 --- a/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRecommendedContent.kt +++ b/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRecommendedContent.kt @@ -24,7 +24,7 @@ class GetRecommendedContent @Inject constructor( override suspend fun doWork(params: Unit): List = withContext(dispatchers.io) { if (firebaseAuth.currentUser != null) { val response = recommendationRepository - .getRecommendations(firebaseAuth.currentUser!!.uid) + .getRecommendedContent(firebaseAuth.currentUser!!.uid) val itemIds = response.getOrThrow().items.map { it.objectX.id } val query = ArchiveQuery().booksByIdentifiers(itemIds) diff --git a/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRelatedContent.kt b/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRelatedContent.kt new file mode 100644 index 000000000..7a9ff8f0d --- /dev/null +++ b/domain/src/main/java/org/kafka/domain/interactors/recommendation/GetRelatedContent.kt @@ -0,0 +1,42 @@ +package org.kafka.domain.interactors.recommendation + +import com.google.firebase.auth.FirebaseAuth +import com.kafka.data.entities.Item +import com.kafka.data.feature.item.ItemRepository +import com.kafka.data.feature.recommendation.RecommendationRepository +import com.kafka.data.model.ArchiveQuery +import com.kafka.data.model.booksByIdentifiers +import kotlinx.coroutines.withContext +import org.kafka.base.CoroutineDispatchers +import org.kafka.base.debug +import org.kafka.base.domain.ResultInteractor +import org.kafka.domain.interactors.query.BuildRemoteQuery +import javax.inject.Inject + +class GetRelatedContent @Inject constructor( + private val recommendationRepository: RecommendationRepository, + private val itemRepository: ItemRepository, + private val buildRemoteQuery: BuildRemoteQuery, + private val firebaseAuth: FirebaseAuth, + private val dispatchers: CoroutineDispatchers +) : ResultInteractor>() { + + override suspend fun doWork(params: String): List = withContext(dispatchers.io) { + if (firebaseAuth.currentUser != null) { + val response = recommendationRepository.getRelatedContent(params) + val itemIds = response.getOrThrow().items.map { it.objectX.id } + + val query = ArchiveQuery().booksByIdentifiers(itemIds) + val items = itemRepository.updateQuery(buildRemoteQuery(query)) + + debug { "Recommended items: ${itemIds.size} $items" } + + items + .filterNot { it.isInappropriate } // remove inappropriate items + .distinctBy { it.itemId } + } else { + emptyList() + } + } + +} diff --git a/ui/components/src/main/java/org/kafka/ui/components/Components.kt b/ui/components/src/main/java/org/kafka/ui/components/Labels.kt similarity index 100% rename from ui/components/src/main/java/org/kafka/ui/components/Components.kt rename to ui/components/src/main/java/org/kafka/ui/components/Labels.kt index 8c04566ae..9482119ee 100644 --- a/ui/components/src/main/java/org/kafka/ui/components/Components.kt +++ b/ui/components/src/main/java/org/kafka/ui/components/Labels.kt @@ -11,8 +11,8 @@ import androidx.compose.ui.unit.dp fun LabelMedium(text: String, modifier: Modifier = Modifier) { Text( text = text, - style = MaterialTheme.typography.titleMedium, modifier = modifier, + style = MaterialTheme.typography.titleMedium, ) } diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt index 65793a08a..fde172d22 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt @@ -3,21 +3,26 @@ package org.kafka.item.detail import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material3.MaterialTheme @@ -32,16 +37,16 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Wallpapers import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.kafka.data.entities.Item import com.kafka.data.entities.ItemDetail import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList import org.kafka.base.debug import org.kafka.common.animation.Delayed import org.kafka.common.extensions.AnimatedVisibilityFade @@ -57,6 +62,7 @@ import org.kafka.navigation.LocalNavigator import org.kafka.ui.components.LabelMedium import org.kafka.ui.components.ProvideScaffoldPadding import org.kafka.ui.components.item.Item +import org.kafka.ui.components.item.RowItem import org.kafka.ui.components.item.SubjectItem import org.kafka.ui.components.progress.InfiniteProgressBar import org.kafka.ui.components.scaffoldPadding @@ -106,6 +112,7 @@ private fun ItemDetail( ItemDetail( state = state, + relatedContent = viewModel.recommendedContent, openDescription = viewModel::showDescription, goToCreator = viewModel::goToCreator, onPrimaryAction = { @@ -124,6 +131,7 @@ private fun ItemDetail( @Composable private fun ItemDetail( state: ItemDetailViewState, + relatedContent: List, openDescription: (String) -> Unit, goToCreator: (String?) -> Unit, onPrimaryAction: (String) -> Unit, @@ -166,12 +174,24 @@ private fun ItemDetail( ) } - if (!state.itemDetail?.subject.isNullOrEmpty()) { + if (state.hasSubjects) { item(span = { GridItemSpan(GridItemSpan) }) { - Subjects( - subjects = state.itemDetail!!.immutableSubjects, - modifier = Modifier.padding(Dimens.Spacing16), - onClicked = openSubject + FlowRow(modifier = Modifier.padding(Dimens.Gutter)) { + state.itemDetail!!.immutableSubjects.forEach { + SubjectItem( + text = it, + modifier = Modifier.padding(Dimens.Spacing04), + onClicked = { openSubject(it) }) + } + } + } + } + + if (relatedContent.isNotEmpty()) { + item { + RelatedItems( + items = relatedContent.toImmutableList(), + openItemDetail = openItemDetail ) } } @@ -180,7 +200,7 @@ private fun ItemDetail( item(span = { GridItemSpan(GridItemSpan) }) { LabelMedium( text = stringResource(R.string.more_by_author), - modifier = Modifier.padding(Dimens.Spacing16) + modifier = Modifier.padding(Dimens.Gutter) ) } @@ -262,37 +282,40 @@ private fun ItemDescription( } @Composable -fun ratingText(rating: Int): AnnotatedString { - return AnnotatedString.Builder().apply { - repeat(rating) { - append("✪") - } - repeat(MaxRating - rating) { - append("✪") - } - - addStyle(SpanStyle(color = MaterialTheme.colorScheme.primary), 0, rating) - append(" ") - }.toAnnotatedString() -} - -@Composable -private fun Subjects( - subjects: ImmutableList, +private fun RelatedItems( + items: ImmutableList, modifier: Modifier = Modifier, - onClicked: (String) -> Unit + openItemDetail: (String) -> Unit ) { - FlowRow(modifier = modifier) { - subjects.forEach { - SubjectItem( - text = it, - modifier = Modifier.padding(Dimens.Spacing04), - onClicked = { onClicked(it) }) + Column(modifier = modifier) { + LabelMedium( + text = stringResource(R.string.you_might_also_like), + modifier = Modifier.padding(Dimens.Gutter) + ) + + LazyRow( + contentPadding = PaddingValues( + horizontal = Dimens.Gutter, + vertical = Dimens.Spacing06 + ), + horizontalArrangement = Arrangement.spacedBy(Dimens.Spacing12) + ) { + items( + items = items, + key = { it.itemId }, + contentType = { it.javaClass } + ) { item -> + RowItem( + item = item, + modifier = Modifier + .widthIn(max = Dimens.CoverSizeLarge.width) + .clickable { openItemDetail(item.itemId) } + ) + } } } } -private const val MaxRating = 5 private const val GridItemSpan = 1 @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, wallpaper = Wallpapers.GREEN_DOMINATED_EXAMPLE) @@ -306,6 +329,7 @@ private fun ItemDetailPreview() { isFavorite = true, itemsByCreator = FakeItemData.fakeItems ), + relatedContent = listOf(), modifier = Modifier.background(Color.White), openDescription = {}, goToCreator = {}, diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt index 588faae15..fd285d68d 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt @@ -4,9 +4,13 @@ import android.app.Activity import android.app.Application import android.content.Context import android.content.ContextWrapper +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.kafka.data.entities.Item import com.kafka.data.entities.ItemDetail import com.kafka.data.feature.item.DownloadStatus import com.kafka.data.model.ArchiveQuery @@ -15,6 +19,7 @@ import com.kafka.data.model.SearchFilter.Subject import com.kafka.data.model.booksByAuthor import com.kafka.remote.config.RemoteConfig import com.kafka.remote.config.isOnlineReaderEnabled +import com.kafka.remote.config.isRelatedContentRowEnabled import com.kafka.remote.config.isShareEnabled import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.StateFlow @@ -36,6 +41,7 @@ import org.kafka.domain.interactors.UpdateItemDetail import org.kafka.domain.interactors.UpdateItems import org.kafka.domain.interactors.recent.AddRecentItem import org.kafka.domain.interactors.recent.IsResumableAudio +import org.kafka.domain.interactors.recommendation.GetRelatedContent import org.kafka.domain.interactors.recommendation.PostRecommendationEvent import org.kafka.domain.interactors.recommendation.PostRecommendationEvent.RecommendationEvent import org.kafka.domain.observers.ObserveCreatorItems @@ -67,6 +73,7 @@ class ItemDetailViewModel @Inject constructor( private val observeFavoriteStatus: ObserveFavoriteStatus, private val updateFavorite: UpdateFavorite, private val postRecommendationEvent: PostRecommendationEvent, + private val getRelatedContent: GetRelatedContent, private val resumeAlbum: ResumeAlbum, private val navigator: Navigator, private val remoteConfig: RemoteConfig, @@ -74,15 +81,20 @@ class ItemDetailViewModel @Inject constructor( private val analytics: Analytics, private val appReviewManager: AppReviewManager, private val application: Application, - savedStateHandle: SavedStateHandle + savedStateHandle: SavedStateHandle, ) : ViewModel() { private val itemId: String = checkNotNull(savedStateHandle["itemId"]) private val loadingState = ObservableLoadingCounter() private val currentRoot get() = navigator.currentRoot.value + var recommendedContent by mutableStateOf(emptyList()) + val state: StateFlow = combine( - observeItemDetail.flow.onEach { updateItemsByAuthor(it?.creator) }, + observeItemDetail.flow.onEach { item -> + updateItemsByCreator(item?.creator) + updateRelatedItems(item?.itemId) + }, observeCreatorItems.flow, observeFavoriteStatus.flow, loadingState.observable, @@ -95,7 +107,7 @@ class ItemDetailViewModel @Inject constructor( isFavorite = isFavorite, isLoading = isLoading, downloadItem = downloadItem, - ctaText = itemDetail?.let { ctaText(itemDetail, isResumableAudio) }.orEmpty() + ctaText = itemDetail?.let { ctaText(itemDetail, isResumableAudio) }.orEmpty(), ) }.stateInDefault( scope = viewModelScope, @@ -172,15 +184,23 @@ class ItemDetailViewModel @Inject constructor( } } - private fun updateItemsByAuthor(creator: String?) { - creator?.let { ArchiveQuery().booksByAuthor(it) }?.let { + private fun updateItemsByCreator(creator: String?) { + creator?.let { ArchiveQuery().booksByAuthor(it) }?.let { query -> viewModelScope.launch { - updateItems(UpdateItems.Params(it)) + updateItems(UpdateItems.Params(query)) .collectStatus(loadingState, snackbarManager) } } } + private fun updateRelatedItems(itemId: String?) { + if (itemId != null && remoteConfig.isRelatedContentRowEnabled()) { + viewModelScope.launch { + recommendedContent = getRelatedContent(itemId).getOrNull().orEmpty() + } + } + } + private fun addRecentItem(itemId: String) { viewModelScope.launch { analytics.log { this.addRecentItem(itemId) } diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewState.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewState.kt index cca6d97ed..11ffc4916 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewState.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewState.kt @@ -19,6 +19,9 @@ data class ItemDetailViewState( val hasItemsByCreator get() = !itemsByCreator.isNullOrEmpty() + val hasSubjects + get() = !itemDetail?.subject.isNullOrEmpty() + val isFullScreenLoading: Boolean get() { debug { "isFullScreenLoading $isLoading $itemDetail" } diff --git a/ui/item/src/main/java/org/kafka/item/detail/description/DescriptionDialog.kt b/ui/item/src/main/java/org/kafka/item/detail/description/DescriptionDialog.kt index 8829dc11e..5023863c8 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/description/DescriptionDialog.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/description/DescriptionDialog.kt @@ -19,6 +19,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -27,7 +28,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.kafka.data.entities.ItemDetail import org.kafka.common.test.testTagUi import org.kafka.item.detail.ItemDetailViewModel -import org.kafka.item.detail.ratingText import org.kafka.ui.components.progress.InfiniteProgressBar import ui.common.theme.theme.Dimens @@ -92,3 +92,20 @@ internal fun DescriptionText( ) } } + +@Composable +private fun ratingText(rating: Int): AnnotatedString { + return AnnotatedString.Builder().apply { + repeat(rating) { + append("✪") + } + repeat(MaxRating - rating) { + append("✪") + } + + addStyle(SpanStyle(color = MaterialTheme.colorScheme.primary), 0, rating) + append(" ") + }.toAnnotatedString() +} + +private const val MaxRating = 5 diff --git a/ui/item/src/main/res/values/strings.xml b/ui/item/src/main/res/values/strings.xml index f822c7012..b94fb9d15 100644 --- a/ui/item/src/main/res/values/strings.xml +++ b/ui/item/src/main/res/values/strings.xml @@ -13,4 +13,5 @@ Download Download file Favorite + You might also like From 2c8eb58a55b2c0e12782db71f774075bbe9425f0 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 22:18:21 +0530 Subject: [PATCH 04/13] remove content type that might clash --- ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt index f92cdc487..d4c0c1079 100644 --- a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt +++ b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt @@ -122,7 +122,7 @@ private fun HomepageFeedItems( ) { homepage.collection.forEachIndexed { index, collection -> if (index == recommendationRowIndex && recommendedContent.isNotEmpty()) { - item(key = "recommendations", contentType = "row") { + item(key = "recommendations") { LabelMedium( text = stringResource(id = R.string.recommended_for_you), modifier = subjectModifier From 1a5b7d344c5d389c1cfb45054ad7f207f10c56d1 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 22:53:49 +0530 Subject: [PATCH 05/13] custom crashlytics keys --- .../kafka/analytics/data/UserDataRepository.kt | 2 +- .../org/kafka/analytics/logger/AnalyticsImpl.kt | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt b/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt index 5c3b07629..2cfbb1403 100644 --- a/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt +++ b/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt @@ -17,6 +17,6 @@ class UserDataRepository @Inject constructor( fun getUserCountry(): String? { val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager - return telephonyManager.networkCountryIso.takeIf { it.isNotBlank() } + return "US" } } diff --git a/core/analytics/src/main/java/org/kafka/analytics/logger/AnalyticsImpl.kt b/core/analytics/src/main/java/org/kafka/analytics/logger/AnalyticsImpl.kt index b6a9c146f..e5eb5079c 100644 --- a/core/analytics/src/main/java/org/kafka/analytics/logger/AnalyticsImpl.kt +++ b/core/analytics/src/main/java/org/kafka/analytics/logger/AnalyticsImpl.kt @@ -2,8 +2,11 @@ package org.kafka.analytics.logger import android.content.Context import android.os.Bundle +import com.google.firebase.Firebase import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.ktx.logEvent +import com.google.firebase.crashlytics.crashlytics +import com.google.firebase.crashlytics.setCustomKeys import com.mixpanel.android.mpmetrics.MixpanelAPI import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope @@ -24,6 +27,7 @@ class AnalyticsImpl @Inject constructor( private val eventRepository: EventRepository, ) : Analytics { private val firebaseAnalytics by lazy { FirebaseAnalytics.getInstance(context) } + private val crashlytics by lazy { Firebase.crashlytics } private val mixPanel = MixpanelAPI.getInstance(context, MIXPANEL_TOKEN, true) init { @@ -48,6 +52,17 @@ class AnalyticsImpl @Inject constructor( override fun updateUserProperty(userData: UserData) { firebaseAnalytics.setUserProperty("userId", userData.userId) firebaseAnalytics.setUserProperty("country", userData.country) + + if (userData.userId != null) { + crashlytics.setUserId(userData.userId) + mixPanel.identify(userData.userId) + } + + crashlytics.setCustomKeys { + if (userData.country != null) { + key("country", userData.country) + } + } } override fun logScreenView(label: String, route: String?, arguments: Any?) { From 317c620a657a2012b5518323fcc8569a7e4b7686 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Tue, 30 Apr 2024 22:54:07 +0530 Subject: [PATCH 06/13] revert accidental change --- .../main/java/org/kafka/analytics/data/UserDataRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt b/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt index 2cfbb1403..5c3b07629 100644 --- a/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt +++ b/core/analytics/src/main/java/org/kafka/analytics/data/UserDataRepository.kt @@ -17,6 +17,6 @@ class UserDataRepository @Inject constructor( fun getUserCountry(): String? { val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager - return "US" + return telephonyManager.networkCountryIso.takeIf { it.isNotBlank() } } } From 487cc0bc9380045209ad013ac39d5cb0721b555a Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Wed, 1 May 2024 00:06:46 +0530 Subject: [PATCH 07/13] remove constraint layout --- .../user/home/bottombar/rail/ResizableHomeNavigationRail.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/kafka/user/home/bottombar/rail/ResizableHomeNavigationRail.kt b/app/src/main/java/com/kafka/user/home/bottombar/rail/ResizableHomeNavigationRail.kt index 9892e4318..05e8ec6ed 100644 --- a/app/src/main/java/com/kafka/user/home/bottombar/rail/ResizableHomeNavigationRail.kt +++ b/app/src/main/java/com/kafka/user/home/bottombar/rail/ResizableHomeNavigationRail.kt @@ -44,7 +44,6 @@ internal fun RowScope.ResizableHomeNavigationRail( maxWeight = maxWeight, dragOffset = dragOffset, setDragOffset = setDragOffset, - analyticsPrefix = "home.navigationRail", ) { resizableModifier -> HomeNavigationRail( selectedTab = selectedTab, From c6b4af8b5c11be03c7ff1bb354379e8729a3d9a5 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Thu, 2 May 2024 22:40:23 +0530 Subject: [PATCH 08/13] add source to item detail analytics --- app/src/main/java/com/kafka/user/home/AppNavigation.kt | 1 + .../java/org/kafka/homepage/recent/RecentViewModel.kt | 2 +- .../src/main/java/org/kafka/item/detail/ItemDetail.kt | 10 ++++++---- .../java/org/kafka/item/detail/ItemDetailViewModel.kt | 6 ++++-- .../org/kafka/library/downloads/DownloadsViewModel.kt | 2 +- .../org/kafka/library/favorites/FavoriteViewModel.kt | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kafka/user/home/AppNavigation.kt b/app/src/main/java/com/kafka/user/home/AppNavigation.kt index bfb8279f5..8e38d7e04 100644 --- a/app/src/main/java/com/kafka/user/home/AppNavigation.kt +++ b/app/src/main/java/com/kafka/user/home/AppNavigation.kt @@ -142,6 +142,7 @@ private fun NavGraphBuilder.addLibraryRoot() { addWebView(RootScreen.Library) addOnlineReader(RootScreen.Library) addLogin(RootScreen.Library) + addProfile(RootScreen.Library) } } diff --git a/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentViewModel.kt b/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentViewModel.kt index 07b333478..6bdc81fbb 100644 --- a/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentViewModel.kt +++ b/ui/homepage/src/main/java/org/kafka/homepage/recent/RecentViewModel.kt @@ -37,7 +37,7 @@ class RecentViewModel @Inject constructor( } fun openItemDetail(itemId: String) { - analytics.log { this.openItemDetail(itemId) } + analytics.log { this.openItemDetail(itemId = itemId, source = "reading_list") } navigator.navigate(Screen.ItemDetail.createRoute(navigator.currentRoot.value, itemId)) } diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt index fde172d22..2748a6a45 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetail.kt @@ -138,7 +138,7 @@ private fun ItemDetail( openFiles: (String) -> Unit, toggleFavorite: () -> Unit, openSubject: (String) -> Unit, - openItemDetail: (String) -> Unit, + openItemDetail: (String, String) -> Unit, modifier: Modifier = Modifier, lazyGridState: LazyGridState = rememberLazyGridState() ) { @@ -191,7 +191,9 @@ private fun ItemDetail( item { RelatedItems( items = relatedContent.toImmutableList(), - openItemDetail = openItemDetail + openItemDetail = { itemId -> + openItemDetail(itemId, itemDetailSourceRelated) + } ) } } @@ -208,7 +210,7 @@ private fun ItemDetail( Item( item = item, modifier = Modifier - .clickable { openItemDetail(item.itemId) } + .clickable { openItemDetail(item.itemId, itemDetailSourceCreator) } .padding( vertical = Dimens.Spacing06, horizontal = Dimens.Gutter @@ -337,7 +339,7 @@ private fun ItemDetailPreview() { openFiles = {}, toggleFavorite = {}, openSubject = {}, - openItemDetail = {} + openItemDetail = { _, _ -> } ) } } diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt index fd285d68d..9aa76bd04 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt @@ -208,8 +208,8 @@ class ItemDetailViewModel @Inject constructor( } } - fun openItemDetail(itemId: String) { - analytics.log { this.openItemDetail(itemId) } + fun openItemDetail(itemId: String, source: String) { + analytics.log { this.openItemDetail(itemId = itemId, source = source) } navigator.navigate(Screen.ItemDetail.createRoute(currentRoot, itemId)) } @@ -270,3 +270,5 @@ class ItemDetailViewModel @Inject constructor( } private const val itemOpenThresholdForAppReview = 20 +const val itemDetailSourceRelated = "item_detail/related" +const val itemDetailSourceCreator = "item_detail/creator" diff --git a/ui/library/src/main/java/org/kafka/library/downloads/DownloadsViewModel.kt b/ui/library/src/main/java/org/kafka/library/downloads/DownloadsViewModel.kt index 8e6897606..7642ba1d2 100644 --- a/ui/library/src/main/java/org/kafka/library/downloads/DownloadsViewModel.kt +++ b/ui/library/src/main/java/org/kafka/library/downloads/DownloadsViewModel.kt @@ -48,7 +48,7 @@ class DownloadsViewModel @Inject constructor( } fun openItemDetail(itemId: String) { - analytics.log { this.openItemDetail(itemId) } + analytics.log { this.openItemDetail(itemId = itemId, source = "downloads") } navigator.navigate(Screen.ItemDetail.createRoute(navigator.currentRoot.value, itemId)) } diff --git a/ui/library/src/main/java/org/kafka/library/favorites/FavoriteViewModel.kt b/ui/library/src/main/java/org/kafka/library/favorites/FavoriteViewModel.kt index 960ea8006..51a59abef 100644 --- a/ui/library/src/main/java/org/kafka/library/favorites/FavoriteViewModel.kt +++ b/ui/library/src/main/java/org/kafka/library/favorites/FavoriteViewModel.kt @@ -58,7 +58,7 @@ class FavoriteViewModel @Inject constructor( } fun openItemDetail(itemId: String) { - analytics.log { this.openItemDetail(itemId) } + analytics.log { this.openItemDetail(itemId = itemId, source = "favorites") } navigator.navigate(Screen.ItemDetail.createRoute(navigator.currentRoot.value, itemId)) } From 1ed2af26a03a581a6fafe9364f833d949d712836 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Sat, 4 May 2024 13:02:42 +0530 Subject: [PATCH 09/13] Make Search arguments optional with a default value - Fixes a crash where arguments were not passed from homepage; --- .../main/java/com/kafka/user/home/AppNavigation.kt | 11 +++++++++-- .../java/com/kafka/user/playback/PlaybackViewModel.kt | 9 +++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kafka/user/home/AppNavigation.kt b/app/src/main/java/com/kafka/user/home/AppNavigation.kt index 8e38d7e04..a4b2551e6 100644 --- a/app/src/main/java/com/kafka/user/home/AppNavigation.kt +++ b/app/src/main/java/com/kafka/user/home/AppNavigation.kt @@ -28,6 +28,7 @@ import androidx.navigation.compose.navigation import androidx.navigation.navArgument import androidx.navigation.navDeepLink import com.google.accompanist.navigation.material.bottomSheet +import com.kafka.data.model.SearchFilter import com.kafka.reader.ReaderScreen import com.kafka.reader.online.OnlineReader import com.kafka.search.SearchScreen @@ -156,8 +157,14 @@ private fun NavGraphBuilder.addSearch(root: RootScreen) { composable( Screen.Search.createRoute(root), arguments = listOf( - navArgument("keyword") { type = NavType.StringType }, - navArgument("filters") { type = NavType.StringType } + navArgument("keyword") { + type = NavType.StringType + defaultValue = "" + }, + navArgument("filters") { + type = NavType.StringType + defaultValue = SearchFilter.Name.name + } ), deepLinks = listOf( navDeepLink { diff --git a/app/src/main/java/com/kafka/user/playback/PlaybackViewModel.kt b/app/src/main/java/com/kafka/user/playback/PlaybackViewModel.kt index 9924c22e4..610029722 100644 --- a/app/src/main/java/com/kafka/user/playback/PlaybackViewModel.kt +++ b/app/src/main/java/com/kafka/user/playback/PlaybackViewModel.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.kafka.navigation.Navigator import org.kafka.navigation.Screen -import org.kafka.navigation.Screen.Search.createRoute +import org.kafka.navigation.Screen.Search import javax.inject.Inject @HiltViewModel @@ -46,7 +46,12 @@ class PlaybackViewModel @Inject constructor( viewModelScope.launch { val currentRoot = navigator.currentRoot.value val creator = playbackConnection.nowPlaying.value.artist - navigator.navigate(createRoute(currentRoot, creator, SearchFilter.Creator.name)) + + navigator.navigate(Search.createRoute( + root = currentRoot, + keyword = creator, + filter = SearchFilter.Creator.name + )) } } } From c6e323cd431710a8ade5ba93f502e3fac2abcab6 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Sat, 4 May 2024 13:12:01 +0530 Subject: [PATCH 10/13] Placeholder loading for grid items --- .../main/java/org/kafka/homepage/Homepage.kt | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt index d4c0c1079..110e4b482 100644 --- a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt +++ b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt @@ -178,9 +178,9 @@ private fun HomepageFeedItems( item(key = collection.key, contentType = "grid") { SubjectItems(collection.labels, goToSubject) GridItems( - items = collection.items, + collection = collection, openItemDetail = openItemDetail, - modifier = Modifier.testTag("row_$index") + modifier = Modifier.testTag("grid_$index") ) } } @@ -336,7 +336,7 @@ private fun LazyListScope.columnItems( @Composable private fun GridItems( - items: ImmutableList, + collection: HomepageCollection.Grid, openItemDetail: (String) -> Unit, modifier: Modifier = Modifier, lazyListState: LazyGridState = rememberLazyGridState() @@ -346,21 +346,34 @@ private fun GridItems( modifier = modifier.height(HorizontalGridHeight.dp), state = lazyListState ) { - items( - items = items, - key = { it.itemId }, - contentType = { "item" } - ) { item -> - ItemSmall( - item = item, - modifier = Modifier - .widthIn(max = RowItemMaxWidth.dp) - .clickable { openItemDetail(item.itemId) } - .padding( + if (collection.items.isNotEmpty()) { + items( + items = collection.items, + key = { it.itemId }, + contentType = { "item" } + ) { item -> + ItemSmall( + item = item, + modifier = Modifier + .widthIn(max = RowItemMaxWidth.dp) + .clickable { openItemDetail(item.itemId) } + .padding( + horizontal = Dimens.Gutter, + vertical = Dimens.Spacing06 + ) + ) + } + } else { + items( + count = PlaceholderItemCount, + key = { index -> "grid_placeholder_${collection.key}_$index" }) { + ItemPlaceholder( + Modifier.padding( horizontal = Dimens.Gutter, vertical = Dimens.Spacing06 ) - ) + ) + } } } } @@ -383,4 +396,4 @@ private val subjectModifier = Modifier private const val HorizontalGridHeight = 290 private const val RowItemMaxWidth = 350 -private const val PlaceholderItemCount = 5 +private const val PlaceholderItemCount = 6 From 6720cae53dca7b96ed4c8700ff3faec606c45404 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Sat, 4 May 2024 13:12:10 +0530 Subject: [PATCH 11/13] Release 0.20.0 --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e890ebf9c..c96396476 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ android { defaultConfig { applicationId = "com.kafka.user" - versionCode = 59 - versionName = "0.19.0" + versionCode = 60 + versionName = "0.20.0" val properties = Properties() properties.load(project.rootProject.file("local.properties").inputStream()) From 77cc2dfce3bc2dcbe60f8aa1df72628f843fdda8 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Sat, 4 May 2024 13:21:32 +0530 Subject: [PATCH 12/13] Add analytics for recommendation row --- ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt | 4 +++- .../src/main/java/org/kafka/homepage/HomepageViewModel.kt | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt index 110e4b482..c38ce0dd2 100644 --- a/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt +++ b/ui/homepage/src/main/java/org/kafka/homepage/Homepage.kt @@ -76,6 +76,7 @@ fun Homepage(viewModel: HomepageViewModel = hiltViewModel()) { recommendedContent = viewModel.recommendedContent, recommendationRowIndex = viewModel.recommendationRowIndex, openItemDetail = viewModel::openItemDetail, + openRecommendationDetail = viewModel::openRecommendationDetail, openRecentItemDetail = viewModel::openRecentItemDetail, removeRecentItem = viewModel::removeRecentItem, goToSearch = viewModel::openSearch, @@ -109,6 +110,7 @@ private fun HomepageFeedItems( recommendationRowIndex: Int, openRecentItemDetail: (String) -> Unit, openItemDetail: (String) -> Unit, + openRecommendationDetail: (String) -> Unit, removeRecentItem: (String) -> Unit, goToSearch: () -> Unit, goToSubject: (String) -> Unit, @@ -129,7 +131,7 @@ private fun HomepageFeedItems( ) RowItems( items = recommendedContent.toImmutableList(), - openItemDetail = openItemDetail + openItemDetail = openRecommendationDetail ) } } diff --git a/ui/homepage/src/main/java/org/kafka/homepage/HomepageViewModel.kt b/ui/homepage/src/main/java/org/kafka/homepage/HomepageViewModel.kt index 3811725e3..073308137 100644 --- a/ui/homepage/src/main/java/org/kafka/homepage/HomepageViewModel.kt +++ b/ui/homepage/src/main/java/org/kafka/homepage/HomepageViewModel.kt @@ -90,8 +90,12 @@ class HomepageViewModel @Inject constructor( navigator.navigate(Screen.Profile.createRoute(navigator.currentRoot.value)) } - fun openItemDetail(itemId: String) { - analytics.log { openItemDetail(itemId, "homepage") } + fun openRecommendationDetail(itemId: String) { + openItemDetail(itemId, "recommendation") + } + + fun openItemDetail(itemId: String, source: String = "homepage") { + analytics.log { openItemDetail(itemId, source) } navigator.navigate(Screen.ItemDetail.createRoute(navigator.currentRoot.value, itemId)) } From b9f51dc1bd1b3d7ae0f6e1b73ca72c8c26fa8ec7 Mon Sep 17 00:00:00 2001 From: vipulkumar Date: Sat, 4 May 2024 13:25:17 +0530 Subject: [PATCH 13/13] Add audio index to analytics --- .../src/main/java/org/kafka/analytics/EventRepository.kt | 3 ++- .../main/java/org/kafka/domain/interactors/ResumeAlbum.kt | 6 +++++- .../main/java/org/kafka/item/detail/ItemDetailViewModel.kt | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/analytics/src/main/java/org/kafka/analytics/EventRepository.kt b/core/analytics/src/main/java/org/kafka/analytics/EventRepository.kt index cd600345a..5b1188ea6 100644 --- a/core/analytics/src/main/java/org/kafka/analytics/EventRepository.kt +++ b/core/analytics/src/main/java/org/kafka/analytics/EventRepository.kt @@ -19,9 +19,10 @@ class EventRepository @Inject constructor() { "name" to name, ) - fun playItem(itemId: String, source: String? = null) = "play_item" to mapOf( + fun playItem(itemId: String, source: String? = null, index: Int = 0) = "play_item" to mapOf( "item_id" to itemId, "source" to source, + "index" to index.toString(), ) fun readItem(itemId: String, type: String = "offline", source: String? = null) = diff --git a/domain/src/main/java/org/kafka/domain/interactors/ResumeAlbum.kt b/domain/src/main/java/org/kafka/domain/interactors/ResumeAlbum.kt index 2bbc0f1f4..68b56d743 100644 --- a/domain/src/main/java/org/kafka/domain/interactors/ResumeAlbum.kt +++ b/domain/src/main/java/org/kafka/domain/interactors/ResumeAlbum.kt @@ -3,6 +3,7 @@ package org.kafka.domain.interactors import com.kafka.data.dao.RecentAudioDao import com.sarahang.playback.core.PlaybackConnection import com.sarahang.playback.core.apis.AudioDataSource +import org.kafka.analytics.logger.Analytics import org.kafka.base.domain.Interactor import javax.inject.Inject @@ -13,7 +14,8 @@ import javax.inject.Inject class ResumeAlbum @Inject constructor( private val playbackConnection: PlaybackConnection, private val recentAudioDao: RecentAudioDao, - private val audioDataSource: AudioDataSource + private val audioDataSource: AudioDataSource, + private val analytics: Analytics ) : Interactor() { override suspend fun doWork(params: String) { @@ -25,6 +27,8 @@ class ResumeAlbum @Inject constructor( .indexOf(audio?.fileId) .coerceAtLeast(0) + analytics.log { playItem(itemId = params, index = index) } + playbackConnection.playAlbum(params, index) } } diff --git a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt index 9aa76bd04..b6b80b611 100644 --- a/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt +++ b/ui/item/src/main/java/org/kafka/item/detail/ItemDetailViewModel.kt @@ -141,7 +141,6 @@ class ItemDetailViewModel @Inject constructor( fun onPrimaryAction(itemId: String) { if (state.value.itemDetail!!.isAudio) { addRecentItem(itemId) - analytics.log { playItem(itemId) } viewModelScope.launch { resumeAlbum(itemId).collect() } } else { openReader(itemId)