diff --git a/.github/workflows/call-build.yml b/.github/workflows/call-build.yml index 52968ac8..f7944546 100644 --- a/.github/workflows/call-build.yml +++ b/.github/workflows/call-build.yml @@ -29,19 +29,10 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v2 - - name: Restore bundle cache - uses: actions/cache@v3 + - name: Setup Ruby + uses: ruby/setup-ruby@cd48c8e22733480b66887b42bfeb6c0b88ea1a56 with: - path: vendor/bundle - key: bundle-${{ hashFiles('**/Gemfile.lock') }} - - - name: Restore gradle cache - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle', '**/*.gradle.kts') }} + bundler-cache: true - name: Create release keystore run: echo "${{ secrets.RELEASE_KEYSTORE }}" | base64 -d > gradle/keystore/release.jks diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..a7c65144 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "daifuku" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..2f62cc6a --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,19 @@ +GEM + remote: https://rubygems.org/ + specs: + daifuku (0.9.0) + nokogiri (~> 1.15) + redcarpet (~> 3.6) + nokogiri (1.15.5-arm64-darwin) + racc (~> 1.4) + racc (1.7.3) + redcarpet (3.6.0) + +PLATFORMS + arm64-darwin-22 + +DEPENDENCIES + daifuku + +BUNDLED WITH + 2.4.22 diff --git a/README-JA.md b/README-JA.md index 6badcc90..3e37295b 100644 --- a/README-JA.md +++ b/README-JA.md @@ -66,13 +66,14 @@ FANBOX には Web 版しかなく、スマートフォンで投稿を閲覧す - 画像 / ファイル / GIF 形式でダウンロード - 投稿に含まれるすべての画像をダウンロード - ファンカードのダウンロード + - クリエイター単位での一括ダウンロード機能 +- 広告 + - AdMob Native 広告 #### Not Ready... -- クリエイター単位での一括ダウンロード機能 - Pixiv 連携機能 - ウィジェット機能 -- 広告系全般 ## Architecture アプリのアーキテクチャ図を示します。 だいぶ複雑になっているので、一部のモジュールや依存関係は省略し、概略を掴める形にしています。 @@ -120,6 +121,8 @@ graph LR ## Contribute +セットアップはとても簡単で、このリポジトリをクローン氏 `bundle install` するだけです。このアプリは [daifuku](https://github.com/cookpad/daifuku) と [Puree](https://github.com/cookpad/puree-kotlin) を用いてログ基盤を作成しています。詳しくはライブラリのドキュメントまたは `./scripts/daifuku` 以下をご覧ください。 + このアプリは Gradle の Convention Plugins を用いてビルドのロジックを共通化しており、`build-logic` というモジュールに全てのロジックが記述されています。このアプローチに関しては、[nowinandroid](https://github.com/matsumo0922/nowinandroid/tree/main/build-logic) をご覧ください。 何か不具合を発見したり機能を改善したい場合、機能を新たに開発したい場合は、まず issue を書いてください。その上であなた自身を assign し、開発に取り組んでください。pull request はいつでも歓迎です :smile: diff --git a/README.md b/README.md index c1c774e0..73859843 100644 --- a/README.md +++ b/README.md @@ -68,13 +68,14 @@ There was only a web version of FANBOX, which was a bit inconvenient for viewing - Download in image/file/GIF format. - Download all images included in a post. - Download fan cards. + - Bulk download function for individual creators. +- Ads + - AdMob Native Ads #### Not Ready... -- Bulk download function for individual creators. - Pixiv integration feature. - Widget functionality. -- All advertising-related features. ## Architecture Shows the architecture diagram of the app. It's quite complex, so I've omitted some modules and dependencies to give you an overview. @@ -122,11 +123,13 @@ graph LR ## Contribute +Setup is very easy, just clone this repository and `bundle install`. This app uses [daifuku](https:github.comcookpaddaifuku) and [Puree](https:github.comcookpadpuree-kotlin) to create the log infrastructure. For more information, please see the library documentation or `./scripts/daifuku`. + This app uses Gradle's Convention Plugins to standardize the build logic, and all the logic is written in a module called `build-logic`. For information on this approach, see [nowinandroid](https://github.com/matsumo0922/nowinandroid/tree/main/build-logic). If you find a bug, want to improve a feature, or want to develop a new feature, please first write an issue. Then assign yourself and work on the development. Pull requests are always welcome :smile: -This app is monetized using AdMob. When building manually from GitHub, you need to write the AdMob App ID in `local.properties`. By default it contains a dummy ID, which causes it to crash on startup. Alternatively, please delete the AdMob code and build the app. In addition, various IDs are described in `local.properties`. See `appbuild.gradle.kts` or `PixiViewConfig` for details. +This app is monetized using AdMob. When building manually from GitHub, you need to write the AdMob App ID in `local.properties`. By default it contains a dummy ID, which causes it to crash on startup. Alternatively, please delete the AdMob code and build the app. In addition, various IDs are described in `local.properties`. See `app/build.gradle.kts` or `PixiViewConfig` for details. ## License diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fc6fe499..9a220ae8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -126,6 +126,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:ui")) implementation(project(":core:billing")) + implementation(project(":core:logs")) implementation(project(":feature:report")) implementation(project(":feature:library")) @@ -139,6 +140,8 @@ dependencies { implementation(libs.bundles.ktor) implementation(libs.androidx.core.splashscreen) + implementation(libs.play.review) + implementation(libs.play.update) implementation(libs.play.service.oss) implementation(libs.play.service.ads) implementation(libs.google.material) diff --git a/app/src/main/java/caios/android/fanbox/MainActivity.kt b/app/src/main/java/caios/android/fanbox/MainActivity.kt index 660c1a43..683d1486 100644 --- a/app/src/main/java/caios/android/fanbox/MainActivity.kt +++ b/app/src/main/java/caios/android/fanbox/MainActivity.kt @@ -49,7 +49,9 @@ import caios.android.fanbox.core.ui.view.LoadingView import caios.android.fanbox.feature.post.service.PostDownloadService import caios.android.fanbox.ui.PixiViewApp import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.google.android.play.core.review.ReviewManagerFactory import dagger.hilt.android.AndroidEntryPoint +import timber.log.Timber @AndroidEntryPoint class MainActivity : FragmentActivity(), PostDownloader { @@ -192,6 +194,7 @@ class MainActivity : FragmentActivity(), PostDownloader { override fun onDownloadImages(imageItems: List) { if (isPostDownloadServiceBound) { + showReviewDialog() startForegroundService(Intent(this, PostDownloadService::class.java)) postDownloadService.downloadImages(imageItems) } else { @@ -201,6 +204,7 @@ class MainActivity : FragmentActivity(), PostDownloader { override fun onDownloadFile(fileItem: FanboxPostDetail.FileItem) { if (isPostDownloadServiceBound) { + showReviewDialog() startForegroundService(Intent(this, PostDownloadService::class.java)) postDownloadService.downloadFile(fileItem) } else { @@ -210,6 +214,7 @@ class MainActivity : FragmentActivity(), PostDownloader { override fun onDownloadPosts(posts: List, isIgnoreFree: Boolean, isIgnoreFile: Boolean) { if (isPostDownloadServiceBound) { + showReviewDialog() startForegroundService(Intent(this, PostDownloadService::class.java)) postDownloadService.downloadPosts(posts, isIgnoreFree, isIgnoreFile) } else { @@ -226,6 +231,26 @@ class MainActivity : FragmentActivity(), PostDownloader { } } + private fun showReviewDialog() { + if (!viewModel.isAbleToRequestReview()) return + + val manager = ReviewManagerFactory.create(this) + val request = manager.requestReviewFlow() + + request.addOnCompleteListener { + if (it.isSuccessful) { + val reviewInfo = it.result + val flow = manager.launchReviewFlow(this, reviewInfo) + + flow.addOnCanceledListener { + ToastUtil.show(this, R.string.home_review_success) + } + } else { + Timber.d("Review request failed: ${it.exception}") + } + } + } + @Composable private fun shouldUseDarkTheme(screenState: ScreenState): Boolean { return when (screenState) { diff --git a/app/src/main/java/caios/android/fanbox/MainViewModel.kt b/app/src/main/java/caios/android/fanbox/MainViewModel.kt index 5b3b4116..53a62460 100644 --- a/app/src/main/java/caios/android/fanbox/MainViewModel.kt +++ b/app/src/main/java/caios/android/fanbox/MainViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import caios.android.fanbox.core.billing.BillingClient import caios.android.fanbox.core.common.util.suspendRunCatching +import caios.android.fanbox.core.datastore.PreferenceLaunchLog import caios.android.fanbox.core.model.ScreenState import caios.android.fanbox.core.model.UserData import caios.android.fanbox.core.model.fanbox.FanboxMetaData @@ -20,6 +21,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +import java.time.OffsetDateTime import java.util.Timer import java.util.UUID import javax.inject.Inject @@ -33,6 +35,7 @@ class MainViewModel @Inject constructor( billingClient: BillingClient, private val userDataRepository: UserDataRepository, private val fanboxRepository: FanboxRepository, + private val launchLog: PreferenceLaunchLog, ) : ViewModel() { private val _isLoggedInFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) @@ -62,6 +65,7 @@ class MainViewModel @Inject constructor( ) init { + launchLog.save(OffsetDateTime.now()) billingClient.initialize() viewModelScope.launch { @@ -104,6 +108,10 @@ class MainViewModel @Inject constructor( _isAppLockedFlow.emit(isAppLock) } } + + fun isAbleToRequestReview(): Boolean { + return launchLog.get().size >= 3 + } } @Stable diff --git a/app/src/main/java/caios/android/fanbox/PixiViewApplication.kt b/app/src/main/java/caios/android/fanbox/PixiViewApplication.kt index f232d3f8..4ed8dd11 100644 --- a/app/src/main/java/caios/android/fanbox/PixiViewApplication.kt +++ b/app/src/main/java/caios/android/fanbox/PixiViewApplication.kt @@ -5,6 +5,8 @@ import android.content.Intent import android.os.Build import caios.android.fanbox.core.common.PixiViewConfig import caios.android.fanbox.core.common.PixiViewDebugTree +import caios.android.fanbox.core.logs.puree.PureeConfigurator +import caios.android.fanbox.core.repository.UserDataRepository import caios.android.fanbox.feature.report.CrashReportActivity import coil.Coil import coil.ImageLoader @@ -17,12 +19,18 @@ import com.google.android.material.color.DynamicColors import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseOptions import dagger.hilt.android.HiltAndroidApp +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @HiltAndroidApp class PixiViewApplication : Application() { + @Inject + lateinit var userDataRepository: UserDataRepository + @Inject lateinit var pixiViewConfig: PixiViewConfig @@ -39,8 +47,8 @@ class PixiViewApplication : Application() { startCrushReportActivity(e) } + setupLogger() setupCoil() - setupFirebase() } @@ -101,4 +109,14 @@ class PixiViewApplication : Application() { FirebaseApp.initializeApp(this, builder.build()) } + + private fun setupLogger() { + MainScope().launch { + PureeConfigurator.configure( + context = this@PixiViewApplication, + pixiViewConfig = pixiViewConfig, + userData = userDataRepository.userData.first(), + ) + } + } } diff --git a/core/billing/build.gradle.kts b/core/billing/build.gradle.kts index dffbb8e8..c3dc86ff 100644 --- a/core/billing/build.gradle.kts +++ b/core/billing/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { implementation(project(":core:common")) implementation(project(":core:repository")) implementation(project(":core:datastore")) + implementation(project(":core:logs")) api(libs.bundles.billing) } diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts index 3e1df621..776f8181 100644 --- a/core/datastore/build.gradle.kts +++ b/core/datastore/build.gradle.kts @@ -31,6 +31,7 @@ protobuf { dependencies { implementation(project(":core:common")) implementation(project(":core:model")) + implementation(project(":core:logs")) implementation(libs.androidx.datastore) implementation(libs.protobuf.kotlin.lite) diff --git a/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PixiViewPreferencesDataStore.kt b/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PixiViewPreferencesDataStore.kt index c9808f05..abe593f3 100644 --- a/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PixiViewPreferencesDataStore.kt +++ b/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PixiViewPreferencesDataStore.kt @@ -40,7 +40,7 @@ class PixiViewPreferencesDataStore( isGridMode = if (it.hasIsGridMode()) it.isGridMode else false, isFollowTabDefaultHome = if (it.hasIsFollowTabDefaultHome()) it.isFollowTabDefaultHome else false, isHideAdultContents = if (it.hasIsHideAdultContents()) it.isHideAdultContents else true, - isOverrideAdultContents = if (it.hasIsOverrideAdultContents()) it.isOverrideAdultContents else false, + isOverrideAdultContents = if (it.hasIsOverrideAdultContents()) it.isOverrideAdultContents else true, isPlusMode = if (it.hasIsPlusMode()) it.isPlusMode else false, isAgreedPrivacyPolicy = if (it.hasIsAgreedPrivacyPolicy()) it.isAgreedPrivacyPolicy else false, isAgreedTermsOfService = if (it.hasIsAgreedTermsOfService()) it.isAgreedTermsOfService else false, diff --git a/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PreferenceLaunchLog.kt b/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PreferenceLaunchLog.kt new file mode 100644 index 00000000..b5270fb8 --- /dev/null +++ b/core/datastore/src/main/java/caios/android/fanbox/core/datastore/PreferenceLaunchLog.kt @@ -0,0 +1,37 @@ +package caios.android.fanbox.core.datastore + +import android.content.Context +import caios.android.fanbox.core.common.serializer.OffsetDateTimeSerializer +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.json.Json +import java.io.File +import java.time.OffsetDateTime +import javax.inject.Inject + +class PreferenceLaunchLog @Inject constructor( + @ApplicationContext private val context: Context, +) { + private val logFile get() = File(context.filesDir, FILE_NAME) + + fun save(time: OffsetDateTime) { + val logs = get().toMutableList() + val serializer = ListSerializer(OffsetDateTimeSerializer()) + + Json.encodeToString(serializer, logs.apply { add(time) }).also { + logFile.writeText(it) + } + } + + fun get(): List { + if (!logFile.exists()) return emptyList() + + return logFile.readText().let { + Json.decodeFromString(ListSerializer(OffsetDateTimeSerializer()), it) + } + } + + companion object { + private const val FILE_NAME = "LaunchLog.json" + } +} diff --git a/core/logs/.gitignore b/core/logs/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/core/logs/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/core/logs/build.gradle.kts b/core/logs/build.gradle.kts new file mode 100644 index 00000000..66f152ec --- /dev/null +++ b/core/logs/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("pixiview.library") + id("pixiview.detekt") + id("pixiview.hilt") + id("pixiview.firebase") + alias(libs.plugins.protobuf) +} + +android { + namespace = "caios.android.fanbox.core.logs" +} + +dependencies { + implementation(project(":core:common")) + implementation(project(":core:model")) + + implementation(libs.puree) +} diff --git a/core/logs/src/main/AndroidManifest.xml b/core/logs/src/main/AndroidManifest.xml new file mode 100644 index 00000000..8bdb7e14 --- /dev/null +++ b/core/logs/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/CommonPayload.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/CommonPayload.kt new file mode 100644 index 00000000..8c379268 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/CommonPayload.kt @@ -0,0 +1,42 @@ +package caios.android.fanbox.core.logs + +import org.json.JSONObject + +// This class is automatically generated by generate-log-classes. +data class CommonPayload( + // ユーザー識別用の UUID + // データ削除でリセットされる + val pixiviewId: String, + // ユーザーエージェント + // ex) caios.android.fanbox/11; Android/28; SOV36; KDDI; f608ac4c29 + val userAgent: String, + // FanboxViewer+ ユーザーか + val isPlus: Boolean, + // 開発者モードか + val isDeveloper: Boolean, + // テスターか + val isTester: Boolean, + // Android OSバージョン + val osVersion: String, + // アプリケーションのビルドバリアント(release/debug/billing) + val applicationVariant: String, + // アプリケーション VersionCode (212700131 のような数値) + val applicationVersionCode: Long, + // アプリケーション VersionName (21.27.0.13 のような文字列) + val applicationVersionName: String, + // タイムゾーン(Asia/Tokyoなど) + val timeZone: String, +) { + fun applyToJsonObject(jsonLog: JSONObject) = jsonLog.apply { + put("pixiview_id", pixiviewId) + put("user_agent", userAgent) + put("is_plus", isPlus) + put("is_developer", isDeveloper) + put("is_tester", isTester) + put("os_version", osVersion) + put("application_variant", applicationVariant) + put("application_version_code", applicationVersionCode) + put("application_version_name", applicationVersionName) + put("time_zone", timeZone) + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/category/LogCategory.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/category/LogCategory.kt new file mode 100644 index 00000000..0a418b51 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/category/LogCategory.kt @@ -0,0 +1,7 @@ +package caios.android.fanbox.core.logs.category + +import kotlinx.serialization.json.JsonObject + +interface LogCategory { + val properties: JsonObject +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/category/NavigationLog.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/category/NavigationLog.kt new file mode 100644 index 00000000..1ea2c9df --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/category/NavigationLog.kt @@ -0,0 +1,25 @@ +package caios.android.fanbox.core.logs.category + +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put + +// This class is automatically generated by generate-log-classes. +sealed class NavigationLog : LogCategory { + class Navigate internal constructor( + private val screenRoute: String, + ) : NavigationLog() { + override val properties: JsonObject = buildJsonObject { + put("event_category", "navigation") + put("event_name", "navigate") + put("screen_route", screenRoute) + } + } + + companion object { + // 画面遷移したときのログ + fun navigate( + screenRoute: String, + ) = Navigate(screenRoute) + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogFilter.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogFilter.kt new file mode 100644 index 00000000..38a87af0 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogFilter.kt @@ -0,0 +1,34 @@ +package caios.android.fanbox.core.logs.puree + +import android.os.Build +import caios.android.fanbox.core.common.PixiViewConfig +import caios.android.fanbox.core.logs.CommonPayload +import caios.android.fanbox.core.model.BuildConfig +import caios.android.fanbox.core.model.UserData +import com.cookpad.puree.kotlin.PureeFilter +import org.json.JSONObject +import java.time.ZoneId + +class PixiViewLogFilter( + private val pixiViewConfig: PixiViewConfig, + private val userData: UserData, + private val userAgent: String, +) : PureeFilter { + + override fun applyFilter(log: JSONObject): JSONObject { + val commonPayload = CommonPayload( + pixiviewId = userData.pixiViewId, + userAgent = userAgent, + isPlus = userData.isPlusMode, + isDeveloper = userData.isDeveloperMode, + isTester = userData.isTestUser, + osVersion = Build.VERSION.SDK_INT.toString(), + applicationVariant = BuildConfig.BUILD_TYPE, + applicationVersionCode = pixiViewConfig.versionCode.toLong(), + applicationVersionName = pixiViewConfig.versionName, + timeZone = ZoneId.systemDefault().id, + ) + + return commonPayload.applyToJsonObject(log) + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogOutput.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogOutput.kt new file mode 100644 index 00000000..8b7bc833 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogOutput.kt @@ -0,0 +1,16 @@ +package caios.android.fanbox.core.logs.puree + +import com.cookpad.puree.kotlin.output.PureeBufferedOutput +import org.json.JSONObject +import timber.log.Timber +import java.time.Duration + +class PixiViewLogOutput : PureeBufferedOutput("pixiview_activity_log") { + + override val flushInterval: Duration = Duration.ofSeconds(15) + + override fun emit(logs: List, onSuccess: () -> Unit, onFailed: (Throwable) -> Unit) { + Timber.d("PureeLog: $logs") + onSuccess.invoke() + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogger.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogger.kt new file mode 100644 index 00000000..b9525c62 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PixiViewLogger.kt @@ -0,0 +1,38 @@ +package caios.android.fanbox.core.logs.puree + +import caios.android.fanbox.core.logs.category.LogCategory +import com.cookpad.puree.kotlin.PureeLog +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put + +internal object PixiViewActivityLogger { + fun post(logCategory: LogCategory) = logCategory.run { + PixiViewActivityLog(properties).also { + Puree.send(it) + } + } +} + +@Serializable +data class PixiViewActivityLog internal constructor( + private var properties: JsonObject, +) : PureeLog { + + init { + properties = buildJsonObject { + for (key in properties.keys) { + put(key, properties[key]!!) + } + + put("table_name", tableName) + } + } + + companion object { + private const val tableName: String = "android_pixiview_activity" + } +} + +fun LogCategory.send() = PixiViewActivityLogger.post(this) diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/Puree.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/Puree.kt new file mode 100644 index 00000000..0c78cfa9 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/Puree.kt @@ -0,0 +1,39 @@ +package caios.android.fanbox.core.logs.puree + +import com.cookpad.puree.kotlin.PureeLog +import com.cookpad.puree.kotlin.PureeLogger + +object Puree { + private var pureeLoggerInstance: LoggerWrapper? = null + private val pureeLogger: LoggerWrapper + get() = checkNotNull(pureeLoggerInstance) { "PureeLogger instance is not set" } + + fun setPureeLogger(pureeLogger: LoggerWrapper) { + pureeLoggerInstance = pureeLogger + } + + @JvmStatic + fun send(log: PureeLog) { + pureeLogger.postLog(log) + } + + @JvmStatic + fun flush() { + pureeLogger.flush() + } + + interface LoggerWrapper { + fun postLog(log: PureeLog) + fun flush() + } +} + +class PureeLoggerWrapper(private val logger: PureeLogger) : Puree.LoggerWrapper { + override fun postLog(log: PureeLog) { + logger.postLog(log) + } + + override fun flush() { + logger.flush() + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeConfigurator.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeConfigurator.kt new file mode 100644 index 00000000..6e25f735 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeConfigurator.kt @@ -0,0 +1,55 @@ +package caios.android.fanbox.core.logs.puree + +import android.content.Context +import androidx.lifecycle.ProcessLifecycleOwner +import caios.android.fanbox.core.common.PixiViewConfig +import caios.android.fanbox.core.model.UserData +import com.cookpad.puree.kotlin.PureeLogger +import com.cookpad.puree.kotlin.store.DbPureeLogStore +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json + +object PureeConfigurator { + + @OptIn(ExperimentalSerializationApi::class) + private val formatter = Json { + isLenient = true + prettyPrint = true + ignoreUnknownKeys = true + coerceInputValues = true + encodeDefaults = true + explicitNulls = false + } + + fun configure( + context: Context, + pixiViewConfig: PixiViewConfig, + userData: UserData, + ) { + val logger = buildPureeLogger(context, pixiViewConfig, userData) + + Puree.setPureeLogger(PureeLoggerWrapper(logger)) + Puree.flush() + } + + private fun buildPureeLogger( + context: Context, + pixiViewConfig: PixiViewConfig, + userData: UserData, + ): PureeLogger { + return PureeLogger.Builder( + lifecycle = ProcessLifecycleOwner.get().lifecycle, + logSerializer = PureeKotlinSerializer(formatter), + logStore = DbPureeLogStore(context, "puree-kotlin.db"), + ) + .filter( + PixiViewLogFilter(pixiViewConfig, userData, userAgent = "PixiView"), + PixiViewActivityLog::class.java, + ) + .output( + PixiViewLogOutput(), + PixiViewActivityLog::class.java, + ) + .build() + } +} diff --git a/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeKotlinSerializer.kt b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeKotlinSerializer.kt new file mode 100644 index 00000000..b5488159 --- /dev/null +++ b/core/logs/src/main/java/caios/android/fanbox/core/logs/puree/PureeKotlinSerializer.kt @@ -0,0 +1,15 @@ +package caios.android.fanbox.core.logs.puree + +import com.cookpad.puree.kotlin.PureeLog +import com.cookpad.puree.kotlin.serializer.PureeLogSerializer +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import org.json.JSONObject + +class PureeKotlinSerializer( + private val formatter: Json, +) : PureeLogSerializer { + override fun serialize(log: PureeLog): JSONObject { + return JSONObject(formatter.encodeToString(log as PixiViewActivityLog)) + } +} diff --git a/core/repository/build.gradle.kts b/core/repository/build.gradle.kts index 3110e543..b36f1b0d 100644 --- a/core/repository/build.gradle.kts +++ b/core/repository/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { implementation(project(":core:common")) implementation(project(":core:model")) implementation(project(":core:datastore")) + implementation(project(":core:logs")) implementation(libs.bundles.ktor) implementation(libs.androidx.paging) diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index 16b30a8e..0bb1a433 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { implementation(project(":core:common")) implementation(project(":core:repository")) implementation(project(":core:datastore")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) diff --git a/core/ui/src/main/java/caios/android/fanbox/core/ui/extensition/NavigationExtension.kt b/core/ui/src/main/java/caios/android/fanbox/core/ui/extensition/NavigationExtension.kt index 8e2a14ec..851efc38 100644 --- a/core/ui/src/main/java/caios/android/fanbox/core/ui/extensition/NavigationExtension.kt +++ b/core/ui/src/main/java/caios/android/fanbox/core/ui/extensition/NavigationExtension.kt @@ -4,6 +4,9 @@ import androidx.navigation.NavController import androidx.navigation.NavOptions import androidx.navigation.NavOptionsBuilder import androidx.navigation.Navigator +import androidx.navigation.navOptions +import caios.android.fanbox.core.logs.category.NavigationLog +import caios.android.fanbox.core.logs.puree.send /** * The navigation result callback between two call screens. @@ -59,7 +62,7 @@ fun NavController.navigateForResult( navigatorExtras: Navigator.Extras? = null, ) { setNavResultCallback(navResultCallback) - navigate(route, navOptions, navigatorExtras) + navigateWithLog(route, navOptions, navigatorExtras) } /** @@ -78,5 +81,14 @@ fun NavController.navigateForResult( builder: NavOptionsBuilder.() -> Unit, ) { setNavResultCallback(navResultCallback) - navigate(route, builder) + navigateWithLog(route, navOptions(builder)) +} + +fun NavController.navigateWithLog( + route: String, + navOptions: NavOptions? = null, + navigatorExtras: Navigator.Extras? = null, +) { + NavigationLog.navigate(route).send() + navigate(route, navOptions, navigatorExtras) } diff --git a/core/ui/src/main/res/values-ja/strings.xml b/core/ui/src/main/res/values-ja/strings.xml index 86499589..baf43238 100644 --- a/core/ui/src/main/res/values-ja/strings.xml +++ b/core/ui/src/main/res/values-ja/strings.xml @@ -91,6 +91,7 @@ 支援中 認証が必要です アプリを使用するにはロック解除が必要です + レビューありがとうございました 投稿を確認 diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index a5af0bdf..9ad55e9d 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -91,6 +91,7 @@ Supporting Authentication required App must be unlocked to use + Thank you for your review Check post detail diff --git a/feature/about/build.gradle.kts b/feature/about/build.gradle.kts index 67eefd04..c68cc78f 100644 --- a/feature/about/build.gradle.kts +++ b/feature/about/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(project(":core:datastore")) implementation(project(":core:ui")) implementation(project(":core:billing")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) } diff --git a/feature/about/src/main/java/caios/android/fanbox/feature/about/about/AboutNavigation.kt b/feature/about/src/main/java/caios/android/fanbox/feature/about/about/AboutNavigation.kt index 439cf4c7..f59d537b 100644 --- a/feature/about/src/main/java/caios/android/fanbox/feature/about/about/AboutNavigation.kt +++ b/feature/about/src/main/java/caios/android/fanbox/feature/about/about/AboutNavigation.kt @@ -7,12 +7,13 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.model.Version import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import kotlinx.collections.immutable.ImmutableList const val AboutRoute = "about" fun NavController.navigateToAbout() { - this.navigate(AboutRoute) + this.navigateWithLog(AboutRoute) } fun NavGraphBuilder.aboutScreen( diff --git a/feature/about/src/main/java/caios/android/fanbox/feature/about/billing/BillingPlusNavigation.kt b/feature/about/src/main/java/caios/android/fanbox/feature/about/billing/BillingPlusNavigation.kt index a4d21e3a..824ae157 100644 --- a/feature/about/src/main/java/caios/android/fanbox/feature/about/billing/BillingPlusNavigation.kt +++ b/feature/about/src/main/java/caios/android/fanbox/feature/about/billing/BillingPlusNavigation.kt @@ -4,13 +4,14 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.ui.Modifier import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import caios.android.fanbox.core.ui.extensition.navigateWithLog import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi import com.google.accompanist.navigation.material.bottomSheet const val BillingPlusRoute = "billingPlus" fun NavController.navigateToBillingPlus() { - this.navigate(BillingPlusRoute) + this.navigateWithLog(BillingPlusRoute) } @OptIn(ExperimentalMaterialNavigationApi::class) diff --git a/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryNavigation.kt b/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryNavigation.kt index 7e2b6d1a..839736ca 100644 --- a/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryNavigation.kt +++ b/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryNavigation.kt @@ -4,13 +4,14 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.ui.Modifier import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import caios.android.fanbox.core.ui.extensition.navigateWithLog import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi import com.google.accompanist.navigation.material.bottomSheet const val VersionHistoryRoute = "versionHistory" fun NavController.navigateToVersionHistory() { - this.navigate("versionHistory") + this.navigateWithLog("versionHistory") } @OptIn(ExperimentalMaterialNavigationApi::class) diff --git a/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryViewModel.kt b/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryViewModel.kt index e1fe08ee..eb83fe96 100644 --- a/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryViewModel.kt +++ b/feature/about/src/main/java/caios/android/fanbox/feature/about/versions/VersionHistoryViewModel.kt @@ -27,7 +27,7 @@ class VersionHistoryViewModel @Inject constructor( fetch() } - fun fetch() { + private fun fetch() { viewModelScope.launch { _screenState.value = ScreenState.Loading _screenState.value = suspendRunCatching { diff --git a/feature/creator/build.gradle.kts b/feature/creator/build.gradle.kts index 0f970689..493917ea 100644 --- a/feature/creator/build.gradle.kts +++ b/feature/creator/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:datastore")) implementation(project(":core:ui")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) implementation(libs.androidx.palette) diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/download/CreatorPostsDownloadNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/download/CreatorPostsDownloadNavigation.kt index edebc51e..c8ea9d9b 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/download/CreatorPostsDownloadNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/download/CreatorPostsDownloadNavigation.kt @@ -8,12 +8,13 @@ import androidx.navigation.NavType import androidx.navigation.compose.dialog import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.CreatorId +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val CreatorPostsDownloadId = "creatorPostsDownloadId" const val CreatorPostsDownloadRoute = "creatorPostsDownload/{$CreatorPostsDownloadId}" fun NavController.navigateToCreatorPostsDownload(creatorId: CreatorId) { - this.navigate("creatorPostsDownload/$creatorId") + this.navigateWithLog("creatorPostsDownload/$creatorId") } fun NavGraphBuilder.creatorPostsDownloadDialog( diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/fancard/FanCardNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/fancard/FanCardNavigation.kt index f7060d70..46f18649 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/fancard/FanCardNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/fancard/FanCardNavigation.kt @@ -9,12 +9,13 @@ import androidx.navigation.compose.composable import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val FanCardId = "fanCardId" const val FanCardRoute = "fanCard/{$FanCardId}" fun NavController.navigateToFanCard(creatorId: CreatorId) { - this.navigate("fanCard/$creatorId") + this.navigateWithLog("fanCard/$creatorId") } fun NavGraphBuilder.fanCardScreen( diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/follow/FollowingCreatorsNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/follow/FollowingCreatorsNavigation.kt index d688a498..224944c9 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/follow/FollowingCreatorsNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/follow/FollowingCreatorsNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val FollowingCreatorsRoute = "followingCreators" fun NavController.navigateToFollowingCreators(navOptions: NavOptions? = null) { - this.navigate(FollowingCreatorsRoute, navOptions) + this.navigateWithLog(FollowingCreatorsRoute, navOptions) } fun NavGraphBuilder.followingCreatorsScreen( diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/payment/PaymentsNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/payment/PaymentsNavigation.kt index c92cf8bd..99d9184a 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/payment/PaymentsNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/payment/PaymentsNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val PaymentsRoute = "payments" fun NavController.navigateToPayments(navOptions: NavOptions? = null) { - this.navigate(PaymentsRoute, navOptions) + this.navigateWithLog(PaymentsRoute, navOptions) } fun NavGraphBuilder.paymentsScreen( diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/support/SupportingCreatorsNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/support/SupportingCreatorsNavigation.kt index 0fd133f6..b7dd8ed5 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/support/SupportingCreatorsNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/support/SupportingCreatorsNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val SupportingCreatorsRoute = "supportingCreators" fun NavController.navigateToSupportingCreators(navOptions: NavOptions? = null) { - this.navigate(SupportingCreatorsRoute, navOptions) + this.navigateWithLog(SupportingCreatorsRoute, navOptions) } fun NavGraphBuilder.supportingCreatorsScreen( diff --git a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/top/CreatorTopNavigation.kt b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/top/CreatorTopNavigation.kt index d51c06b4..917d297a 100644 --- a/feature/creator/src/main/java/caios/android/fanbox/feature/creator/top/CreatorTopNavigation.kt +++ b/feature/creator/src/main/java/caios/android/fanbox/feature/creator/top/CreatorTopNavigation.kt @@ -10,13 +10,14 @@ import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val CreatorTopId = "creatorTopId" const val CreatorTopIsPosts = "creatorTopIsPosts" const val CreatorTopRoute = "creatorTop/{$CreatorTopId}/{$CreatorTopIsPosts}" fun NavController.navigateToCreatorTop(creatorId: CreatorId, isPosts: Boolean = false) { - this.navigate("creatorTop/$creatorId/$isPosts") + this.navigateWithLog("creatorTop/$creatorId/$isPosts") } fun NavGraphBuilder.creatorTopScreen( diff --git a/feature/library/build.gradle.kts b/feature/library/build.gradle.kts index 6f3830fa..8bdb82ed 100644 --- a/feature/library/build.gradle.kts +++ b/feature/library/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(project(":core:datastore")) implementation(project(":core:ui")) implementation(project(":core:billing")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) implementation(libs.pinch.zoom.grid) diff --git a/feature/library/src/main/java/caios/android/fanbox/feature/library/LibraryNavigation.kt b/feature/library/src/main/java/caios/android/fanbox/feature/library/LibraryNavigation.kt index 374f6939..bb05ac73 100644 --- a/feature/library/src/main/java/caios/android/fanbox/feature/library/LibraryNavigation.kt +++ b/feature/library/src/main/java/caios/android/fanbox/feature/library/LibraryNavigation.kt @@ -8,12 +8,13 @@ import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import caios.android.fanbox.core.ui.view.SimpleAlertContents const val LibraryRoute = "library" fun NavController.navigateToLibrary() { - this.navigate(LibraryRoute) + this.navigateWithLog(LibraryRoute) } fun NavGraphBuilder.libraryScreen( diff --git a/feature/library/src/main/java/caios/android/fanbox/feature/library/discovery/LibraryDiscoveryNavigation.kt b/feature/library/src/main/java/caios/android/fanbox/feature/library/discovery/LibraryDiscoveryNavigation.kt index 5284ce94..221fef71 100644 --- a/feature/library/src/main/java/caios/android/fanbox/feature/library/discovery/LibraryDiscoveryNavigation.kt +++ b/feature/library/src/main/java/caios/android/fanbox/feature/library/discovery/LibraryDiscoveryNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val LibraryDiscoveryRoute = "libraryDiscovery" fun NavController.navigateToLibraryDiscovery(navOptions: NavOptions? = null) { - this.navigate(LibraryDiscoveryRoute, navOptions) + this.navigateWithLog(LibraryDiscoveryRoute, navOptions) } fun NavGraphBuilder.libraryDiscoveryScreen( diff --git a/feature/library/src/main/java/caios/android/fanbox/feature/library/home/LibraryHomeNavigation.kt b/feature/library/src/main/java/caios/android/fanbox/feature/library/home/LibraryHomeNavigation.kt index 696c120d..1983151e 100644 --- a/feature/library/src/main/java/caios/android/fanbox/feature/library/home/LibraryHomeNavigation.kt +++ b/feature/library/src/main/java/caios/android/fanbox/feature/library/home/LibraryHomeNavigation.kt @@ -9,12 +9,13 @@ import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import caios.android.fanbox.core.ui.view.SimpleAlertContents const val LibraryHomeRoute = "libraryHome" fun NavController.navigateToLibraryHome(navOptions: NavOptions? = null) { - this.navigate(LibraryHomeRoute, navOptions) + this.navigateWithLog(LibraryHomeRoute, navOptions) } fun NavGraphBuilder.libraryHomeScreen( diff --git a/feature/library/src/main/java/caios/android/fanbox/feature/library/message/LibraryMessageNavigation.kt b/feature/library/src/main/java/caios/android/fanbox/feature/library/message/LibraryMessageNavigation.kt index d817e6f0..5fc82f2f 100644 --- a/feature/library/src/main/java/caios/android/fanbox/feature/library/message/LibraryMessageNavigation.kt +++ b/feature/library/src/main/java/caios/android/fanbox/feature/library/message/LibraryMessageNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val LibraryMessageRoute = "libraryMessage" fun NavController.navigateToLibraryMessage(navOptions: NavOptions? = null) { - this.navigate(LibraryMessageRoute, navOptions) + this.navigateWithLog(LibraryMessageRoute, navOptions) } fun NavGraphBuilder.libraryMessageScreen( diff --git a/feature/library/src/main/java/caios/android/fanbox/feature/library/notify/LibraryNotifyNavigation.kt b/feature/library/src/main/java/caios/android/fanbox/feature/library/notify/LibraryNotifyNavigation.kt index c6c1266d..4a7f7f29 100644 --- a/feature/library/src/main/java/caios/android/fanbox/feature/library/notify/LibraryNotifyNavigation.kt +++ b/feature/library/src/main/java/caios/android/fanbox/feature/library/notify/LibraryNotifyNavigation.kt @@ -10,11 +10,12 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val LibraryNotifyRoute = "libraryNotify" fun NavController.navigateToLibraryNotify(navOptions: NavOptions? = null) { - this.navigate(LibraryNotifyRoute, navOptions) + this.navigateWithLog(LibraryNotifyRoute, navOptions) } fun NavGraphBuilder.libraryNotifyScreen( diff --git a/feature/post/build.gradle.kts b/feature/post/build.gradle.kts index f2ca7757..fed4c25e 100644 --- a/feature/post/build.gradle.kts +++ b/feature/post/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:datastore")) implementation(project(":core:ui")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) implementation(libs.zoomable) diff --git a/feature/post/src/main/java/caios/android/fanbox/feature/post/bookmark/BookmarkedPostsNavigation.kt b/feature/post/src/main/java/caios/android/fanbox/feature/post/bookmark/BookmarkedPostsNavigation.kt index 7341db80..87577282 100644 --- a/feature/post/src/main/java/caios/android/fanbox/feature/post/bookmark/BookmarkedPostsNavigation.kt +++ b/feature/post/src/main/java/caios/android/fanbox/feature/post/bookmark/BookmarkedPostsNavigation.kt @@ -8,11 +8,12 @@ import androidx.navigation.compose.composable import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val BookmarkedPostsRoute = "bookmarkedPosts" fun NavController.navigateToBookmarkedPosts() { - this.navigate(BookmarkedPostsRoute) + this.navigateWithLog(BookmarkedPostsRoute) } fun NavGraphBuilder.bookmarkedPostsScreen( diff --git a/feature/post/src/main/java/caios/android/fanbox/feature/post/detail/PostDetailNavigation.kt b/feature/post/src/main/java/caios/android/fanbox/feature/post/detail/PostDetailNavigation.kt index b5e7d739..4fc8a5a5 100644 --- a/feature/post/src/main/java/caios/android/fanbox/feature/post/detail/PostDetailNavigation.kt +++ b/feature/post/src/main/java/caios/android/fanbox/feature/post/detail/PostDetailNavigation.kt @@ -12,6 +12,7 @@ import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import caios.android.fanbox.core.ui.view.SimpleAlertContents const val PostDetailId = "postDetailId" @@ -19,7 +20,7 @@ const val PostDetailType = "postDetailPagingType" const val PostDetailRoute = "postDetail/{$PostDetailId}/{$PostDetailType}" fun NavController.navigateToPostDetail(postId: PostId, pagingType: PostDetailPagingType) { - this.navigate("postDetail/$postId/${pagingType.name}") + this.navigateWithLog("postDetail/$postId/${pagingType.name}") } fun NavGraphBuilder.postDetailScreen( diff --git a/feature/post/src/main/java/caios/android/fanbox/feature/post/image/PostImageNavigation.kt b/feature/post/src/main/java/caios/android/fanbox/feature/post/image/PostImageNavigation.kt index 9a545453..a86fcbcc 100644 --- a/feature/post/src/main/java/caios/android/fanbox/feature/post/image/PostImageNavigation.kt +++ b/feature/post/src/main/java/caios/android/fanbox/feature/post/image/PostImageNavigation.kt @@ -9,13 +9,14 @@ import androidx.navigation.compose.composable import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val PostImageId = "postImageId" const val PostImageIndex = "postImageIndex" const val PostImageRoute = "postImage/{$PostImageId}/{$PostImageIndex}" fun NavController.navigateToPostImage(postId: PostId, index: Int) { - this.navigate("postImage/$postId/$index") + this.navigateWithLog("postImage/$postId/$index") } fun NavGraphBuilder.postImageScreen( diff --git a/feature/post/src/main/java/caios/android/fanbox/feature/post/search/PostSearchNavigation.kt b/feature/post/src/main/java/caios/android/fanbox/feature/post/search/PostSearchNavigation.kt index a101c1e3..064e68ef 100644 --- a/feature/post/src/main/java/caios/android/fanbox/feature/post/search/PostSearchNavigation.kt +++ b/feature/post/src/main/java/caios/android/fanbox/feature/post/search/PostSearchNavigation.kt @@ -8,6 +8,7 @@ import androidx.navigation.navArgument import caios.android.fanbox.core.model.fanbox.id.CreatorId import caios.android.fanbox.core.model.fanbox.id.PostId import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import java.net.URLDecoder import java.net.URLEncoder @@ -19,7 +20,7 @@ fun NavController.navigateToPostSearch(creatorId: CreatorId? = null, creatorQuer val encodedQuery = URLEncoder.encode(query, Charsets.UTF_8.name()) val route = if (parseQuery(query).mode != PostSearchMode.Unknown) "postSearch/$encodedQuery" else "postSearch/pixiViewUnknown" - this.navigate(route) + this.navigateWithLog(route) } fun NavGraphBuilder.postSearchScreen( diff --git a/feature/report/build.gradle.kts b/feature/report/build.gradle.kts index 3f7de8da..f8b171ec 100644 --- a/feature/report/build.gradle.kts +++ b/feature/report/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:datastore")) implementation(project(":core:ui")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) } diff --git a/feature/setting/build.gradle.kts b/feature/setting/build.gradle.kts index 4cd32383..d74b96b0 100644 --- a/feature/setting/build.gradle.kts +++ b/feature/setting/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:datastore")) implementation(project(":core:ui")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) implementation(libs.libraries.ui) diff --git a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/developer/SettingDeveloperNavigation.kt b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/developer/SettingDeveloperNavigation.kt index 543cd568..2eb8b0f0 100644 --- a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/developer/SettingDeveloperNavigation.kt +++ b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/developer/SettingDeveloperNavigation.kt @@ -9,11 +9,12 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.dialog +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val SettingDeveloperRoute = "SettingDeveloper" fun NavController.navigateToSettingDeveloper() { - this.navigate(SettingDeveloperRoute) + this.navigateWithLog(SettingDeveloperRoute) } fun NavGraphBuilder.settingDeveloperDialog( diff --git a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/oss/SettingLicenseNavigation.kt b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/oss/SettingLicenseNavigation.kt index ed9ba8b4..fc89344f 100644 --- a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/oss/SettingLicenseNavigation.kt +++ b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/oss/SettingLicenseNavigation.kt @@ -6,11 +6,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val SettingLicenseRoute = "SettingLicense" fun NavController.navigateToSettingLicense() { - this.navigate(SettingLicenseRoute) + this.navigateWithLog(SettingLicenseRoute) } fun NavGraphBuilder.settingLicenseScreen( diff --git a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/theme/SettingThemeNavigation.kt b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/theme/SettingThemeNavigation.kt index f43cb97c..2a7e6519 100644 --- a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/theme/SettingThemeNavigation.kt +++ b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/theme/SettingThemeNavigation.kt @@ -6,11 +6,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val SettingThemeDialogRoute = "SettingTheme" fun NavController.navigateToSettingTheme() { - this.navigate(SettingThemeDialogRoute) + this.navigateWithLog(SettingThemeDialogRoute) } fun NavGraphBuilder.settingThemeScreen( diff --git a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/top/SettingTopNavigation.kt b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/top/SettingTopNavigation.kt index e8f37d31..54e988a8 100644 --- a/feature/setting/src/main/java/caios/android/fanbox/feature/setting/top/SettingTopNavigation.kt +++ b/feature/setting/src/main/java/caios/android/fanbox/feature/setting/top/SettingTopNavigation.kt @@ -6,12 +6,13 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog import caios.android.fanbox.core.ui.view.SimpleAlertContents const val SettingTopRoute = "settingTop" fun NavController.navigateToSettingTop() { - this.navigate(SettingTopRoute) + this.navigateWithLog(SettingTopRoute) } fun NavGraphBuilder.settingTopScreen( diff --git a/feature/welcome/build.gradle.kts b/feature/welcome/build.gradle.kts index ebdbccc8..bb8c914f 100644 --- a/feature/welcome/build.gradle.kts +++ b/feature/welcome/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(project(":core:repository")) implementation(project(":core:datastore")) implementation(project(":core:ui")) + implementation(project(":core:logs")) implementation(libs.bundles.ui.implementation) } diff --git a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/login/WelcomeLoginNavigation.kt b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/login/WelcomeLoginNavigation.kt index bc39dea5..38092905 100644 --- a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/login/WelcomeLoginNavigation.kt +++ b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/login/WelcomeLoginNavigation.kt @@ -6,11 +6,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val WelcomeLoginRoute = "welcomeLogin" fun NavController.navigateToWelcomeLogin() { - this.navigate(WelcomeLoginRoute) + this.navigateWithLog(WelcomeLoginRoute) } fun NavGraphBuilder.welcomeLoginScreen( diff --git a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/permission/WelcomePermissionNavigation.kt b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/permission/WelcomePermissionNavigation.kt index 03be74c0..78b59d6b 100644 --- a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/permission/WelcomePermissionNavigation.kt +++ b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/permission/WelcomePermissionNavigation.kt @@ -6,11 +6,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val WelcomePermissionRoute = "welcomePermission" fun NavController.navigateToWelcomePermission() { - this.navigate(WelcomePermissionRoute) + this.navigateWithLog(WelcomePermissionRoute) } fun NavGraphBuilder.welcomePermissionScreen( diff --git a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/top/WelcomeTopNavigation.kt b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/top/WelcomeTopNavigation.kt index 75a4b41c..74892f87 100644 --- a/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/top/WelcomeTopNavigation.kt +++ b/feature/welcome/src/main/java/caios/android/fanbox/feature/welcome/top/WelcomeTopNavigation.kt @@ -6,11 +6,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import caios.android.fanbox.core.ui.animation.NavigateAnimation +import caios.android.fanbox.core.ui.extensition.navigateWithLog const val WelcomeTopRoute = "welcomeTop" fun NavController.navigateToWelcomeTop() { - this.navigate(WelcomeTopRoute) + this.navigateWithLog(WelcomeTopRoute) } fun NavGraphBuilder.welcomeTopScreen( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 91c53bf1..9cc8b253 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,6 +50,8 @@ androidxGlance = "1.0.0" androidxGranceWear = "1.0.0-alpha05" # Google +playReview = "2.0.1" +playUpdate = "2.1.0" playServiceAds = "22.6.0" playServiceOss = "17.0.1" material = "1.10.0" @@ -65,6 +67,9 @@ protobufPlugin = "0.9.4" # Billing billing = "6.1.0" +# Log +puree = "1.4.0" + # Others dagger = "2.49" ktor = "2.3.4" @@ -81,7 +86,7 @@ ffmpeg = "5.1" twitterComposeRule = "0.0.26" # Debugs -firebase = "32.6.0" +firebase = "32.7.0" leakCanary = "2.12" flipper = "0.240.0" timber = "5.0.1" @@ -192,6 +197,8 @@ billing = { module = "com.android.billingclient:billing", version.ref = "billing billing-ktx = { module = "com.android.billingclient:billing-ktx", version.ref = "billing" } # Google +play-review = { module = "com.google.android.play:review-ktx", version.ref = "playReview" } +play-update = { module = "com.google.android.play:app-update-ktx", version.ref = "playUpdate" } play-service-oss = { module = "com.google.android.gms:play-services-oss-licenses", version.ref = "playServiceOss" } play-service-ads = { module = "com.google.android.gms:play-services-ads", version.ref = "playServiceAds" } google-material = { module = "com.google.android.material:material", version.ref = "material" } @@ -225,6 +232,9 @@ ktot-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } protobuf-kotlin-lite = { group = "com.google.protobuf", name = "protobuf-kotlin-lite", version.ref = "protobuf" } protobuf-protoc = { group = "com.google.protobuf", name = "protoc", version.ref = "protobuf" } +# Log +puree = { module = "com.cookpad.puree-kotlin:puree-kotlin", version.ref = "puree" } + # Others dagger-hilt = { module = "com.google.dagger:hilt-android", version.ref = "dagger" } dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" } @@ -269,6 +279,7 @@ infra-api = [ "kotlinx-datetime", "kotlinx-serialization-json", "kotlinx-collections-immutable", + "puree", "timber", ] diff --git a/scripts/daifuku/generate-log-classes b/scripts/daifuku/generate-log-classes new file mode 100755 index 00000000..011ed303 --- /dev/null +++ b/scripts/daifuku/generate-log-classes @@ -0,0 +1,171 @@ +#!/usr/bin/env ruby +require 'daifuku' +require 'erb' +require 'active_support/inflector' + +ROOT_PATH = File.absolute_path(File.join(__dir__, '../../')) +LOG_DEFINITIONS = File.join(ROOT_PATH, 'scripts', 'daifuku', 'log_definitions') +TEMPLATE_DIR = File.join(ROOT_PATH, 'scripts', 'daifuku', 'templates') +DESTINATION_ROOT = File.join(ROOT_PATH, 'core', 'logs', 'src', 'main', 'java', 'caios', 'android', 'fanbox', 'core', 'logs') +KOTLIN_TYPE_MAPS = { + 'smallint' => 'Short', + 'integer' => 'Int', + 'bigint' => 'Long', + 'real' => 'Float', + 'double' => 'Double', + 'boolean' => 'Boolean', + 'string' => 'String', + 'date' => 'java.time.LocalDate', + 'timestamptz' => 'java.time.LocalDateTime', +} +UNSUPPORTED_TYPES = %w(timestamp) + +class CategoryRepresentation + def initialize(category) + @category = category + end + + def name + @category.name + end + + def class_name + @category.name.camelize(:upper) + end + + def descriptions + @category.descriptions + end + + def variable_name + @category.name.camelize(:lower) + end + + def events + @events ||= @category.events.map { |_, event| EventRepresentation.new(event) } + end + + def available_events + events.reject(&:obsolete?) + end +end + +class EventRepresentation + def initialize(event) + @event = event + end + + def name + @event.name + end + + def class_name + @event.name.camelize(:upper) + end + + def variable_name + @event.name.camelize(:lower) + end + + def columns + @columns ||= @event.columns.reject(&:obsolete?).map { |column| ColumnRepresentation.new(column) } + end + + def descriptions + @event.descriptions + end + + def pattern_matches + columns.map { |column| "#{column.variable_name}" }&.join(', ') + end + + def obsolete? + @event.obsolete? + end +end + +class ColumnRepresentation + def initialize(column) + @column = column + end + + def variable_name + @column.name.camelize(:lower) + end + + def original_name + @column.name + end + + def kotlin_type + convert_to_kotlin_type(@column) + end + + def descriptions + @column.descriptions + end + + def as_argument + "#{variable_name}: #{kotlin_type}" + end + + def custom_type? + @column.type.custom? + end + + private + def convert_to_kotlin_type(column) + type = column.type + raise "Code builder currently doesn't support #{type.name}." if UNSUPPORTED_TYPES.include?(type.name) + if type.custom? + kotlin_type ||= type.name # custom type + else + kotlin_type = KOTLIN_TYPE_MAPS[type.name] # primitive types + end + if type.optional? + "#{kotlin_type}?" + else + kotlin_type + end + end +end + +class Generator + def initialize + @common_category = categories[COMMON_CATEGORY_NAME] + raise 'Could not found common category. Please define common.md' unless @common_category + end + + def generate_common_payload!(destination) + columns = @common_category.common_columns.reject(&:obsolete?).map { |column| ColumnRepresentation.new(column) } + template = File.open(File.join(TEMPLATE_DIR, 'CommonPayload.kt.erb')).read + b = binding + result = render(template, b) + File.open(destination, 'w').write(result) + end + + def generate_all_log_categories!(destination_dir) + template = File.open(File.join(TEMPLATE_DIR, 'LogCategory.kt.erb')).read + categories.each do |name, original_category| + next if name == COMMON_CATEGORY_NAME + destination = File.join(destination_dir, "#{original_category.name.camelize}Log.kt") + category = CategoryRepresentation.new(original_category) + b = binding + result = render(template, b) + File.open(destination, 'w').write(result) + end + end + + private + def render(template, b) + ERB.new(template, trim_mode: '-').result(b) + end + + def categories + @categories ||= Daifuku::Compiler.new.compile(LOG_DEFINITIONS) + end +end + +generator = Generator.new +generator.generate_common_payload!(File.join(DESTINATION_ROOT, 'CommonPayload.kt')) +generator.generate_all_log_categories!(File.join(DESTINATION_ROOT, 'category')) diff --git a/scripts/daifuku/log_definitions/common.md b/scripts/daifuku/log_definitions/common.md new file mode 100644 index 00000000..f8a33a8f --- /dev/null +++ b/scripts/daifuku/log_definitions/common.md @@ -0,0 +1,24 @@ +# Common + +- pixiview_id: !string 256 + - ユーザー識別用の UUID + - データ削除でリセットされる +- user_agent: !string 1000 + - ユーザーエージェント + - ex) caios.android.fanbox/11; Android/28; SOV36; KDDI; f608ac4c29 +- is_plus: !boolean + - FanboxViewer+ ユーザーか +- is_developer: !boolean + - 開発者モードか +- is_tester: !boolean + - テスターか +- os_version: !string 32 + - Android OSバージョン +- application_variant: !string 32 + - アプリケーションのビルドバリアント(release/debug/billing) +- application_version_code: !bigint + - アプリケーション VersionCode (212700131 のような数値) +- application_version_name: !string 32 + - アプリケーション VersionName (21.27.0.13 のような文字列) +- time_zone: !string 64 + - タイムゾーン(Asia/Tokyoなど) diff --git a/scripts/daifuku/log_definitions/navigation.md b/scripts/daifuku/log_definitions/navigation.md new file mode 100644 index 00000000..9d43a09d --- /dev/null +++ b/scripts/daifuku/log_definitions/navigation.md @@ -0,0 +1,10 @@ +# AppLaunch + +アプリ内の画面遷移に関するイベント + +## navigate + +画面遷移したときのログ + +- screen_route: !string 2000 + - 遷移先の画面 diff --git a/scripts/daifuku/log_definitions/obsoleted/.keep b/scripts/daifuku/log_definitions/obsoleted/.keep new file mode 100644 index 00000000..e69de29b diff --git a/scripts/daifuku/templates/CommonPayload.kt.erb b/scripts/daifuku/templates/CommonPayload.kt.erb new file mode 100644 index 00000000..e452a3d2 --- /dev/null +++ b/scripts/daifuku/templates/CommonPayload.kt.erb @@ -0,0 +1,23 @@ +package caios.android.fanbox.core.logs + +import org.json.JSONObject + +// This class is automatically generated by generate-log-classes. +data class CommonPayload( + <%- columns.each do |column| -%> + <%- column.descriptions.each do |description| -%> + // <%= description %> + <%- end -%> + <%- if column == columns.last-%> + val <%= column.variable_name %>: <%= column.kotlin_type %> + <%- else -%> + val <%= column.variable_name %>: <%= column.kotlin_type %>, + <%- end -%> + <%- end -%> +) { + fun applyToJsonObject(jsonLog: JSONObject) = jsonLog.apply { + <%- columns.each do |column| -%> + put("<%= column.original_name %>", <%= column.variable_name %>) + <%- end -%> + } +} diff --git a/scripts/daifuku/templates/LogCategory.kt.erb b/scripts/daifuku/templates/LogCategory.kt.erb new file mode 100644 index 00000000..92a378ff --- /dev/null +++ b/scripts/daifuku/templates/LogCategory.kt.erb @@ -0,0 +1,62 @@ +package caios.android.fanbox.core.logs.category + +<%- unless category.available_events.empty? -%> +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put + +<%- end -%> +// This class is automatically generated by generate-log-classes. +sealed class <%= category.class_name %>Log : LogCategory { + <%- category.available_events.each do |event| -%> + <%- if event.columns.empty? -%> + class <%= event.class_name %> internal constructor() : <%= category.class_name %>Log() { + <%- else -%> + class <%= event.class_name %> internal constructor( + <%- event.columns.each do |column| -%> + <%- if column == event.columns.last-%> + private val <%= column.as_argument %> + <%- else -%> + private val <%= column.as_argument %>, + <%- end -%> + <%- end -%> + ) : <%= category.class_name %>Log() { + <%- end -%> + override val properties: JsonObject = buildJsonObject { + put("event_category", "<%= category.name %>") + put("event_name", "<%= event.name %>") + <%- event.columns.each do |column| -%> + <%- if column.custom_type? -%> + put("<%= column.original_name %>", <%= column.variable_name %>.toString()) + <%- else -%> + put("<%= column.original_name %>", <%= column.variable_name %>) + <%- end -%> + <%- end -%> + } + } + + <%- end -%> + companion object { + <%- category.available_events.each do |event| -%> + <%- event.descriptions.each do |description| -%> + // <%= description %> + <%- end -%> + <%- if event.columns.empty? -%> + fun <%= event.variable_name %>() = <%= event.class_name %>(<%= event.pattern_matches %>) + <%- else -%> + fun <%= event.variable_name %>( + <%- event.columns.each do |column| -%> + <%- if column == event.columns.last-%> + <%= column.as_argument %> + <%- else -%> + <%= column.as_argument %>, + <%- end -%> + <%- end -%> + ) = <%= event.class_name %>(<%= event.pattern_matches %>) + <%- end -%> + <%- if event != category.available_events.last-%> + + <%- end -%> + <%- end -%> + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 8b72d65a..feb2cfd1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -29,6 +29,7 @@ include(":core:datastore") include(":core:model") include(":core:common") include(":core:billing") +include(":core:logs") include(":feature:library") include(":feature:report") include(":feature:welcome")