Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data reporting settings #1578

Merged
merged 2 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
- name: Build Android App (skipping benchmark variant)
run: |
./gradlew \
testDebugUnitTest \
:android-app:app:bundle \
:android-app:app:build \
lint \
Expand Down
4 changes: 4 additions & 0 deletions android-app/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
android:name="google_analytics_adid_collection_enabled"
android:value="false" />

<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />

</application>

<queries>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@
package app.tivi.tmdb

import app.tivi.appinitializers.AppInitializer
import app.tivi.util.AppCoroutineDispatchers
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import app.tivi.inject.ApplicationCoroutineScope
import kotlinx.coroutines.launch
import me.tatarka.inject.annotations.Inject

@Inject
class TmdbInitializer(
private val tmdbManager: TmdbManager,
private val dispatchers: AppCoroutineDispatchers,
private val scope: ApplicationCoroutineScope,
) : AppInitializer {
override fun initialize() {
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(dispatchers.main) {
scope.launch {
tmdbManager.refreshConfiguration()
}
}
Expand Down
9 changes: 7 additions & 2 deletions api/tmdb/src/commonMain/kotlin/app/tivi/tmdb/TmdbManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,26 @@ package app.tivi.tmdb
import app.moviebase.tmdb.Tmdb3
import app.moviebase.tmdb.model.TmdbConfiguration
import app.tivi.inject.ApplicationScope
import app.tivi.util.AppCoroutineDispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import me.tatarka.inject.annotations.Inject

@ApplicationScope
@Inject
class TmdbManager(
private val tmdbClient: Tmdb3,
private val dispatchers: AppCoroutineDispatchers,
) {
private val imageProvider = MutableStateFlow(TmdbImageUrlProvider())

fun getLatestImageProvider() = imageProvider.value

suspend fun refreshConfiguration() {
val response = runCatching {
tmdbClient.configuration.getApiConfiguration()
val response = withContext(dispatchers.io) {
runCatching {
tmdbClient.configuration.getApiConfiguration()
}
}

if (response.isSuccess) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,23 @@ package app.tivi.common.imageloading

import android.app.Application
import app.tivi.appinitializers.AppInitializer
import app.tivi.inject.ApplicationCoroutineScope
import app.tivi.util.AppCoroutineDispatchers
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.tatarka.inject.annotations.Inject

@Inject
class CoilCleanupInitializer(
private val application: Application,
private val scope: ApplicationCoroutineScope,
private val dispatchers: AppCoroutineDispatchers,
) : AppInitializer {
@OptIn(DelicateCoroutinesApi::class)
override fun initialize() {
GlobalScope.launch {
withContext(dispatchers.io) {
// We delete Coil's image_cache folder to claim back space for the user
val coilCache = application.cacheDir.resolve("image_cache")
if (coilCache.exists()) {
coilCache.deleteRecursively()
}
scope.launch(dispatchers.io) {
// We delete Coil's image_cache folder to claim back space for the user
val coilCache = application.cacheDir.resolve("image_cache")
if (coilCache.exists()) {
coilCache.deleteRecursively()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ val EnTiviStrings = TiviStrings(
settingsAboutCategoryTitle = "About Tivi",
settingsAppVersion = "Version",
settingsAppVersionSummary = { p0, p1 -> "v%s (%d)".fmt(p0, p1) },
settingsAnalyticsDataCollectionTitle = "Report app usage",
settingsAnalyticsDataCollectionSummary = "Send anonymous details about how you use the application.",
settingsCrashDataCollectionTitle = "Report app crashes",
settingsCrashDataCollectionSummary = "Send anonymous reports about application crashes and other issues.",
settingsDataSaverSummaryOn = "Fetch data less often and display lower quality images",
settingsDataSaverSummaryOff = "Automatically enabled due to system setting",
settingsDataSaverTitle = "Data saver",
Expand All @@ -156,6 +160,7 @@ val EnTiviStrings = TiviStrings(
settingsIgnoreSpecialsSummary = "Automatically ignore specials",
settingsOpenSource = "Open source licenses",
settingsOpenSourceSummary = "Tivi 💞 open source",
settingsPrivacyCategoryTitle = "Privacy",
settingsThemeTitle = "Theme",
settingsTitle = "Settings",
settingsUiCategoryTitle = "User Interface",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ data class TiviStrings(
val settingsAboutCategoryTitle: String,
val settingsAppVersion: String,
val settingsAppVersionSummary: (String, Int) -> String,
val settingsAnalyticsDataCollectionTitle: String,
val settingsAnalyticsDataCollectionSummary: String,
val settingsCrashDataCollectionTitle: String,
val settingsCrashDataCollectionSummary: String,
val settingsDataSaverSummaryOn: String,
val settingsDataSaverSummaryOff: String,
val settingsDataSaverTitle: String,
Expand All @@ -145,6 +149,7 @@ data class TiviStrings(
val settingsIgnoreSpecialsSummary: String,
val settingsOpenSource: String,
val settingsOpenSourceSummary: String,
val settingsPrivacyCategoryTitle: String,
val settingsThemeTitle: String,
val settingsTitle: String,
val settingsUiCategoryTitle: String,
Expand Down
1 change: 1 addition & 0 deletions core/analytics/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ kotlin {
val commonMain by getting {
dependencies {
implementation(projects.core.base)
api(projects.core.preferences)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import me.tatarka.inject.annotations.Provides

@OptIn(ExperimentalMultiplatform::class)
@AllowDifferentMembersInActual
actual interface AnalyticsComponent {
actual interface AnalyticsPlatformComponent {
@ApplicationScope
@Provides
fun provideTiviFirebaseAnalytics(bind: TiviFirebaseAnalytics): Analytics = bind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ class TiviFirebaseAnalytics(
// Ignore, Firebase might not be setup for this project
}
}

override fun setEnabled(enabled: Boolean) {
firebaseAnalytics.setAnalyticsCollectionEnabled(enabled)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ interface Analytics {
name: String,
arguments: Map<String, *>? = null,
)

fun setEnabled(enabled: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,14 @@

package app.tivi.core.analytics

expect interface AnalyticsComponent
import app.tivi.appinitializers.AppInitializer
import me.tatarka.inject.annotations.IntoSet
import me.tatarka.inject.annotations.Provides

expect interface AnalyticsPlatformComponent

interface AnalyticsComponent : AnalyticsPlatformComponent {
@Provides
@IntoSet
fun provideAnalyticsInitializer(impl: AnalyticsInitializer): AppInitializer = impl
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.core.analytics

import app.tivi.appinitializers.AppInitializer
import app.tivi.inject.ApplicationCoroutineScope
import app.tivi.settings.TiviPreferences
import kotlinx.coroutines.launch
import me.tatarka.inject.annotations.Inject

@Inject
class AnalyticsInitializer(
private val preferences: TiviPreferences,
private val scope: ApplicationCoroutineScope,
private val analytics: Analytics,
) : AppInitializer {
override fun initialize() {
scope.launch {
preferences.observeReportAnalytics().collect { enabled ->
analytics.setEnabled(enabled)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import me.tatarka.inject.annotations.Provides

@OptIn(ExperimentalMultiplatform::class)
@AllowDifferentMembersInActual
actual interface AnalyticsComponent {
val analyticsProvider: () -> Analytics

@Provides
@ApplicationScope
fun provideAnalytics(): Analytics = analyticsProvider()
actual interface AnalyticsPlatformComponent {
@get:Provides
@get:ApplicationScope
val analytics: Analytics
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import me.tatarka.inject.annotations.Provides

@OptIn(ExperimentalMultiplatform::class)
@AllowDifferentMembersInActual
actual interface AnalyticsComponent {
actual interface AnalyticsPlatformComponent {
@Provides
@ApplicationScope
fun provideAnalytics(): Analytics = object : Analytics {
override fun trackScreenView(name: String, arguments: Map<String, *>?) = Unit
override fun setEnabled(enabled: Boolean) = Unit
}
}
3 changes: 3 additions & 0 deletions core/base/src/commonMain/kotlin/app/tivi/inject/Scopes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

package app.tivi.inject

import kotlinx.coroutines.CoroutineScope
import me.tatarka.inject.annotations.Scope

@Scope
annotation class ApplicationScope

@Scope
annotation class ActivityScope

typealias ApplicationCoroutineScope = CoroutineScope
2 changes: 2 additions & 0 deletions core/logging/implementation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ kotlin {
dependencies {
api(projects.core.base)
api(projects.core.logging.api)
api(projects.core.preferences)
api(libs.kotlin.coroutines.core)
implementation(libs.kermit.kermit)
implementation(libs.kotlininject.runtime)
Expand All @@ -22,6 +23,7 @@ kotlin {
val androidMain by getting {
dependencies {
implementation(libs.crashkios.crashlytics)
implementation(libs.google.firebase.crashlytics)
implementation(libs.timber)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

import com.google.firebase.crashlytics.FirebaseCrashlytics

internal object AndroidSetCrashReportingEnabledAction : SetCrashReportingEnabledAction {
override fun invoke(enabled: Boolean) {
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(enabled)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ actual interface LoggerPlatformComponent {
@Provides
@IntoSet
fun provideCrashKiOSInitializer(): AppInitializer = AndroidCrashKiOSInitializer

@Provides
fun bindSetCrashReportingEnabledAction(): SetCrashReportingEnabledAction {
return AndroidSetCrashReportingEnabledAction
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

import app.tivi.appinitializers.AppInitializer
import app.tivi.inject.ApplicationCoroutineScope
import app.tivi.settings.TiviPreferences
import kotlinx.coroutines.launch
import me.tatarka.inject.annotations.Inject

@Inject
class CrashReportingInitializer(
private val preferences: TiviPreferences,
private val scope: ApplicationCoroutineScope,
private val action: SetCrashReportingEnabledAction,
) : AppInitializer {
override fun initialize() {
scope.launch {
preferences.observeReportAppCrashes().collect { enabled ->
action(enabled)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package app.tivi.util

import app.tivi.app.ApplicationInfo
import app.tivi.app.Flavor
import app.tivi.appinitializers.AppInitializer
import app.tivi.inject.ApplicationScope
import me.tatarka.inject.annotations.IntoSet
import me.tatarka.inject.annotations.Provides

expect interface LoggerPlatformComponent
Expand All @@ -20,4 +22,8 @@ interface LoggerComponent : LoggerPlatformComponent {
applicationInfo.flavor == Flavor.Qa -> RecordingLoggerImpl()
else -> NoopRecordingLogger
}

@Provides
@IntoSet
fun provideCrashReportingInitializer(impl: CrashReportingInitializer): AppInitializer = impl
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

fun interface SetCrashReportingEnabledAction {
operator fun invoke(enabled: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import me.tatarka.inject.annotations.Provides
@OptIn(ExperimentalMultiplatform::class)
@AllowDifferentMembersInActual
actual interface LoggerPlatformComponent {

@get:Provides
val setCrashReportingEnabledAction: SetCrashReportingEnabledAction

@Provides
@ApplicationScope
fun provideLogger(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,13 @@ actual interface LoggerPlatformComponent {
kermitLogger: KermitLogger,
recordingLogger: RecordingLogger,
): Logger = CompositeLogger(kermitLogger, recordingLogger)

@Provides
fun bindSetCrashReportingEnabledAction(): SetCrashReportingEnabledAction {
return NoopSetCrashReportingEnabledAction
}
}

private object NoopSetCrashReportingEnabledAction : SetCrashReportingEnabledAction {
override fun invoke(enabled: Boolean) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ interface TiviPreferences {
var ignoreSpecials: Boolean
fun observeIgnoreSpecials(): Flow<Boolean>

var reportAppCrashes: Boolean
fun observeReportAppCrashes(): Flow<Boolean>

var reportAnalytics: Boolean
fun observeReportAnalytics(): Flow<Boolean>

var developerHideArtwork: Boolean
fun observeDeveloperHideArtwork(): Flow<Boolean>

Expand Down
Loading