From 430045a8dd8b3f4a160373cf32aad12e3e95d59f Mon Sep 17 00:00:00 2001 From: reditum Date: Fri, 24 May 2024 20:02:34 +0600 Subject: [PATCH] [+] add analytics and callback to skip photos on error --- gradle/libs.versions.toml | 3 ++ tvApp/build.gradle.kts | 4 +++ .../tv/domain/model/synology/PhotoDomain.kt | 12 +++++--- .../office/tv/screen/photo/BestPhotoScreen.kt | 8 ++++- .../screen/photo/components/PhotoSlideShow.kt | 10 +++++-- .../tv/screen/photo/components/PhotoUI.kt | 29 ++++++++++--------- .../office/tv/screen/photo/model/Photo.kt | 6 ++-- tvApp/src/main/res/values/strings.xml | 2 +- 8 files changed, 51 insertions(+), 23 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b6fc962b..242526e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,6 +40,7 @@ essenty = "1.1.0" logback = "1.2.11" shadow = "7.1.2" gms = "20.4.0" +analytics-gms = "4.4.1" [libraries] avif-coder-coil = { module = "com.github.awxkee:avif-coder-coil", version.ref = "avifCoderCoil" } @@ -103,6 +104,7 @@ plugin-kotlin = {module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.r junit = {module = "junit:junit", version.ref = "junit-ver"} androidJunit = {module = "androidx.test.ext:junit", version.ref = "androidJunit-ver"} espresso = {module = "androidx.test.espresso:espresso-core", version.ref = "espresso-ver"} +firebase-analytics = {module = "com.google.firebase:firebase-analytics", version = "22.0.0"} [plugins] kapt = {id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin"} @@ -117,6 +119,7 @@ parcelize = {id = "org.jetbrains.kotlin.plugin.parcelize"} android = {id = "com.android.application"} shadow = {id = "com.github.johnrengelman.shadow"} kotlin = {id = "org.jetbrains.kotlin.multiplatform"} +google-services-gms = {id = "com.google.gms.google-services", version.ref = "analytics-gms"} [bundles] android-core = ["androdx-appCompat", "androidx-activityCompose", "compose-uiTooling", "androdx-activityKtx", "compose-material", "kotlinx-coroutines-android"] diff --git a/tvApp/build.gradle.kts b/tvApp/build.gradle.kts index d9b8cb02..1ec7130f 100644 --- a/tvApp/build.gradle.kts +++ b/tvApp/build.gradle.kts @@ -8,6 +8,7 @@ plugins { id("kotlin-kapt") id("com.google.devtools.ksp").version("1.9.20-1.0.14") alias(libs.plugins.hilt) + id(libs.plugins.google.services.gms.get().pluginId) } val localProperties = Properties() @@ -111,6 +112,9 @@ dependencies { //notion implementation(libs.notion) + //analytics + implementation(libs.firebase.analytics) + //test testImplementation (libs.junit) androidTestImplementation (libs.androidJunit) diff --git a/tvApp/src/main/java/band/effective/office/tv/domain/model/synology/PhotoDomain.kt b/tvApp/src/main/java/band/effective/office/tv/domain/model/synology/PhotoDomain.kt index b1857c29..e29ab4f6 100644 --- a/tvApp/src/main/java/band/effective/office/tv/domain/model/synology/PhotoDomain.kt +++ b/tvApp/src/main/java/band/effective/office/tv/domain/model/synology/PhotoDomain.kt @@ -7,13 +7,15 @@ import band.effective.office.tv.network.synology.models.response.SynologyPhotoSA import java.net.URLEncoder data class PhotoDomain( - val photoThumb: String + val photoThumb: String, + val filename: String, ) fun SynologyListResponse.toDomain(sid: String) = data.files.map { PhotoDomain( - photoThumb = formThumbPhoto(it.path, sid) + photoThumb = formThumbPhoto(it.path, sid), + filename = it.name ) } @@ -31,7 +33,8 @@ fun SynologyPhotoSAlbumsResponse.toDomain(sid: String) = cacheKey = photoInfo.additional.thumbnail.cacheKey, sid = sid, size = size - ) + ), + filename = photoInfo.filename ) } @@ -49,7 +52,8 @@ fun List.toDomain(sid: String) = cacheKey = photoInfo.additional.thumbnail.cacheKey, sid = sid, size = size - ) + ), + filename = photoInfo.filename ) } fun formThumbPhoto(photoPath: String, sid: String): String { diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/photo/BestPhotoScreen.kt b/tvApp/src/main/java/band/effective/office/tv/screen/photo/BestPhotoScreen.kt index 7ae4161f..29b1b950 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/photo/BestPhotoScreen.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/photo/BestPhotoScreen.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.input.key.* import androidx.hilt.navigation.compose.hiltViewModel import androidx.tv.foundation.lazy.list.TvLazyListState import androidx.tv.foundation.lazy.list.rememberTvLazyListState @@ -83,6 +82,11 @@ fun BestPhotoScreen(viewModel: PhotoViewModel = hiltViewModel()) { ) }, onClickPlayButton = { viewModel.sendEvent(BestPhotoEvent.OnClickPlayButton) }, + onError = { num -> + viewModel.sendEvent( + BestPhotoEvent.OnClickNextItem(num) + ) + }, uiState = uiState, playButton = playButton, contentFocus = contentFocus, @@ -98,6 +102,7 @@ private fun PhotoContent( onClickPreviousItemButton: (Int) -> Unit, onClickNextItemButton: (Int) -> Unit, onClickPlayButton: () -> Unit, + onError: (Int) -> Unit, uiState: BestPhotoState, lazyListState: TvLazyListState, contentFocus: FocusRequester, @@ -124,6 +129,7 @@ private fun PhotoContent( down = playButton } .focusable(), + onError = onError, unsafeOkHttpClient = unsafeOkHttpClient ) }, diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoSlideShow.kt b/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoSlideShow.kt index 31702fcb..6743a925 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoSlideShow.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoSlideShow.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.tv.foundation.lazy.list.TvLazyListState import androidx.tv.foundation.lazy.list.TvLazyRow -import androidx.tv.foundation.lazy.list.items +import androidx.tv.foundation.lazy.list.itemsIndexed import androidx.tv.foundation.lazy.list.rememberTvLazyListState import band.effective.office.tv.screen.photo.model.Photo import okhttp3.OkHttpClient @@ -17,6 +17,7 @@ fun PhotoSlideShow( lazyListState: TvLazyListState = rememberTvLazyListState(), modifier: Modifier = Modifier, modifierForFocus: Modifier = Modifier, + onError: (Int) -> Unit, unsafeOkHttpClient: OkHttpClient ) { TvLazyRow( @@ -25,11 +26,16 @@ fun PhotoSlideShow( .fillMaxSize() .focusable() ) { - items(photos) { photo -> + itemsIndexed(photos) { photoIdx, photo -> PhotoUIItem( image = photo, modifier = modifierForFocus .fillMaxSize(), + onError = { + if (lazyListState.firstVisibleItemIndex == photoIdx) { + onError(photoIdx) + } + }, okHttpClient = unsafeOkHttpClient ) } diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoUI.kt b/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoUI.kt index 62214e1b..cd2f013a 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoUI.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/photo/components/PhotoUI.kt @@ -3,32 +3,37 @@ package band.effective.office.tv.screen.photo.components import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import band.effective.office.tv.R import band.effective.office.tv.screen.load.LoadScreen import band.effective.office.tv.screen.photo.model.Photo import coil.ImageLoader import coil.compose.SubcomposeAsyncImage +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.analytics.logEvent import okhttp3.OkHttpClient @Composable -fun PhotoUIItem(image: Photo, modifier: Modifier = Modifier, okHttpClient: OkHttpClient) { +fun PhotoUIItem( + image: Photo, + modifier: Modifier = Modifier, + onError: () -> Unit, + okHttpClient: OkHttpClient +) { + val context = LocalContext.current + val analytics = FirebaseAnalytics.getInstance(context) val photoWith = LocalConfiguration.current.screenWidthDp.dp val photoHeight = LocalConfiguration.current.screenHeightDp.dp - val imageLoader = ImageLoader.Builder(LocalContext.current) + val imageLoader = ImageLoader.Builder(context) .okHttpClient(okHttpClient) .build() @@ -47,13 +52,11 @@ fun PhotoUIItem(image: Photo, modifier: Modifier = Modifier, okHttpClient: OkHtt contentDescription = null, contentScale = ContentScale.Fit, error = { - Text( - text = stringResource(id = R.string.error_show_photo), - fontSize = 40.sp, - color = Color.Red, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxSize() - ) + analytics.logEvent("photo_load_error") { + param("filename", image.filename) + it.result.throwable.message + ?.let { message -> param("error_message", message) } } + onError() } ) } diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/photo/model/Photo.kt b/tvApp/src/main/java/band/effective/office/tv/screen/photo/model/Photo.kt index b8930a02..5d072aa0 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/photo/model/Photo.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/photo/model/Photo.kt @@ -4,11 +4,13 @@ import band.effective.office.tv.core.network.entity.Either import band.effective.office.tv.domain.model.synology.PhotoDomain data class Photo( - val photoThumb: String + val photoThumb: String, + val filename: String, ) fun Either.Success>.toUIModel() = data.map { it.toUIModel() } fun PhotoDomain.toUIModel() = Photo( - photoThumb = photoThumb + photoThumb = photoThumb, + filename = filename ) \ No newline at end of file diff --git a/tvApp/src/main/res/values/strings.xml b/tvApp/src/main/res/values/strings.xml index a4c59c98..d6e42975 100644 --- a/tvApp/src/main/res/values/strings.xml +++ b/tvApp/src/main/res/values/strings.xml @@ -29,7 +29,7 @@ "Tоп по XP" "Топ по дням в ударном режиме" Профиль Duolingo - Мы пока не поддерживаем этот формат фото, позже все будет ок) + Произошла ошибка при загрузке следующего фото: %1$s Best Photo autoplay Выберите минимум одну категорию -- GitLab