Skip to content

Commit eed4c86

Browse files
committed
Merge branch 'develop' into BOOK-288-fix/#158
# Conflicts: # feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt
2 parents cd59711 + 7821d4e commit eed4c86

File tree

26 files changed

+282
-72
lines changed

26 files changed

+282
-72
lines changed

core/common/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ dependencies {
2626

2727
libs.kotlinx.collections.immutable,
2828

29+
platform(libs.firebase.bom),
30+
libs.firebase.analytics,
2931
libs.logger,
3032
)
3133
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.ninecraft.booket.core.common.analytics
2+
3+
import com.google.firebase.analytics.FirebaseAnalytics
4+
import com.google.firebase.analytics.logEvent
5+
import com.orhanobut.logger.Logger
6+
import javax.inject.Inject
7+
import javax.inject.Singleton
8+
9+
@Singleton
10+
class AnalyticsHelper @Inject constructor(
11+
private val firebaseAnalytics: FirebaseAnalytics,
12+
) {
13+
14+
fun logScreenView(screenName: String) {
15+
Logger.d("Analytics - Screen View: $screenName")
16+
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW) {
17+
param(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
18+
}
19+
}
20+
21+
fun logEvent(eventName: String) {
22+
Logger.d("Analytics - Event: $eventName")
23+
firebaseAnalytics.logEvent(eventName) {}
24+
}
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.ninecraft.booket.core.common.analytics.di
2+
3+
import com.google.firebase.Firebase
4+
import com.google.firebase.analytics.FirebaseAnalytics
5+
import com.google.firebase.analytics.analytics
6+
import dagger.Module
7+
import dagger.Provides
8+
import dagger.hilt.InstallIn
9+
import dagger.hilt.components.SingletonComponent
10+
import javax.inject.Singleton
11+
12+
@Module
13+
@InstallIn(SingletonComponent::class)
14+
object AnalyticsModule {
15+
16+
@Provides
17+
@Singleton
18+
fun provideFirebaseAnalytics(): FirebaseAnalytics {
19+
return Firebase.analytics
20+
}
21+
}

core/ui/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies {
1515
projects.core.common,
1616

1717
libs.compose.keyboard.state,
18+
libs.compose.effects,
1819
libs.logger,
1920
)
2021
}

core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/InfinityLazyColumn.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
2323
import androidx.compose.material3.Surface
2424
import androidx.compose.material3.Text
2525
import androidx.compose.runtime.Composable
26-
import androidx.compose.runtime.LaunchedEffect
2726
import androidx.compose.runtime.derivedStateOf
2827
import androidx.compose.runtime.getValue
2928
import androidx.compose.runtime.mutableIntStateOf
@@ -35,6 +34,7 @@ import androidx.compose.ui.Modifier
3534
import androidx.compose.ui.tooling.preview.Preview
3635
import androidx.compose.ui.unit.dp
3736
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
37+
import com.skydoves.compose.effects.RememberedEffect
3838

3939
// 기기에서 평균적으로 한 화면에 보이는 아이템 개수
4040
private const val LIMIT_COUNT = 6
@@ -82,7 +82,7 @@ private fun LazyListState.onLoadMore(
8282
}
8383
}
8484

85-
LaunchedEffect(reached) {
85+
RememberedEffect(reached) {
8686
if (reached && layoutInfo.totalItemsCount > limitCount) action()
8787
}
8888
}

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableIntStateOf
77
import androidx.compose.runtime.mutableStateOf
88
import androidx.compose.runtime.rememberCoroutineScope
99
import androidx.compose.runtime.setValue
10+
import com.ninecraft.booket.core.common.analytics.AnalyticsHelper
1011
import com.ninecraft.booket.core.common.constants.BookStatus
1112
import com.ninecraft.booket.core.common.utils.handleException
1213
import com.ninecraft.booket.core.data.api.repository.BookRepository
@@ -28,6 +29,7 @@ import com.slack.circuit.codegen.annotations.CircuitInject
2829
import com.slack.circuit.retained.rememberRetained
2930
import com.slack.circuit.runtime.Navigator
3031
import com.slack.circuit.runtime.presenter.Presenter
32+
import com.slack.circuitx.effects.ImpressionEffect
3133
import dagger.assisted.Assisted
3234
import dagger.assisted.AssistedFactory
3335
import dagger.assisted.AssistedInject
@@ -46,10 +48,13 @@ class BookDetailPresenter @AssistedInject constructor(
4648
@Assisted private val navigator: Navigator,
4749
private val bookRepository: BookRepository,
4850
private val recordRepository: RecordRepository,
51+
private val analyticsHelper: AnalyticsHelper,
4952
) : Presenter<BookDetailUiState> {
5053
companion object {
5154
private const val PAGE_SIZE = 20
5255
private const val START_INDEX = 0
56+
private const val BOOK_DELETE = "library_book_delete"
57+
private const val BOOK_DELETE_COMPLETE = "library_book_delete_complete"
5358
}
5459

5560
private fun getRecordComparator(sortType: RecordSort): Comparator<ReadingRecordModel> {
@@ -213,6 +218,7 @@ class BookDetailPresenter @AssistedInject constructor(
213218
scope.launch {
214219
bookRepository.deleteBook(userBookId = userBookId)
215220
.onSuccess {
221+
analyticsHelper.logEvent(BOOK_DELETE_COMPLETE)
216222
onSuccess()
217223
}
218224
.onFailure { exception ->
@@ -328,6 +334,7 @@ class BookDetailPresenter @AssistedInject constructor(
328334
is BookDetailUiEvent.OnDeleteRecordClick -> {
329335
isRecordMenuBottomSheetVisible = false
330336
isRecordDeleteDialogVisible = true
337+
analyticsHelper.logEvent(BOOK_DELETE)
331338
}
332339

333340
is BookDetailUiEvent.OnDeleteRecord -> {
@@ -387,6 +394,10 @@ class BookDetailPresenter @AssistedInject constructor(
387394
}
388395
}
389396

397+
ImpressionEffect {
398+
analyticsHelper.logScreenView(screen.name)
399+
}
400+
390401
return BookDetailUiState(
391402
uiState = uiState,
392403
footerState = footerState,

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/card/RecordCardPresenter.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import androidx.compose.runtime.Composable
44
import androidx.compose.runtime.getValue
55
import androidx.compose.runtime.mutableStateOf
66
import androidx.compose.runtime.setValue
7+
import com.ninecraft.booket.core.common.analytics.AnalyticsHelper
78
import com.ninecraft.booket.feature.screens.RecordCardScreen
89
import com.slack.circuit.codegen.annotations.CircuitInject
910
import com.slack.circuit.retained.rememberRetained
1011
import com.slack.circuit.runtime.Navigator
1112
import com.slack.circuit.runtime.presenter.Presenter
13+
import com.slack.circuitx.effects.ImpressionEffect
1214
import dagger.assisted.Assisted
1315
import dagger.assisted.AssistedFactory
1416
import dagger.assisted.AssistedInject
@@ -17,7 +19,14 @@ import dagger.hilt.android.components.ActivityRetainedComponent
1719
class RecordCardPresenter @AssistedInject constructor(
1820
@Assisted private val screen: RecordCardScreen,
1921
@Assisted private val navigator: Navigator,
22+
private val analyticsHelper: AnalyticsHelper,
2023
) : Presenter<RecordCardUiState> {
24+
25+
companion object {
26+
private const val RECORD_CARD_SAVE = "record_card_save"
27+
private const val RECORD_CARD_SHARE = "record_card_share"
28+
}
29+
2130
@Composable
2231
override fun present(): RecordCardUiState {
2332
var isLoading by rememberRetained { mutableStateOf(false) }
@@ -45,16 +54,22 @@ class RecordCardPresenter @AssistedInject constructor(
4554

4655
is RecordCardUiEvent.SaveRecordCard -> {
4756
isCapturing = false
57+
analyticsHelper.logEvent(RECORD_CARD_SAVE)
4858
sideEffect = RecordCardSideEffect.SaveImage(event.bitmap)
4959
}
5060

5161
is RecordCardUiEvent.ShareRecordCard -> {
5262
isSharing = false
63+
analyticsHelper.logEvent(RECORD_CARD_SHARE)
5364
sideEffect = RecordCardSideEffect.ShareImage(event.bitmap)
5465
}
5566
}
5667
}
5768

69+
ImpressionEffect {
70+
analyticsHelper.logScreenView(screen.name)
71+
}
72+
5873
return RecordCardUiState(
5974
isLoading = isLoading,
6075
quote = screen.quote,

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/record/RecordDetailPresenter.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.ninecraft.booket.feature.detail.record
22

33
import androidx.compose.runtime.Composable
4-
import androidx.compose.runtime.LaunchedEffect
54
import androidx.compose.runtime.getValue
65
import androidx.compose.runtime.mutableStateOf
76
import androidx.compose.runtime.rememberCoroutineScope
87
import androidx.compose.runtime.setValue
8+
import com.ninecraft.booket.core.common.analytics.AnalyticsHelper
99
import com.ninecraft.booket.core.common.utils.handleException
1010
import com.ninecraft.booket.core.data.api.repository.RecordRepository
1111
import com.ninecraft.booket.core.model.RecordDetailModel
@@ -16,10 +16,12 @@ import com.ninecraft.booket.feature.screens.RecordEditScreen
1616
import com.ninecraft.booket.feature.screens.arguments.RecordEditArgs
1717
import com.ninecraft.booket.feature.screens.extensions.delayedGoTo
1818
import com.orhanobut.logger.Logger
19+
import com.skydoves.compose.effects.RememberedEffect
1920
import com.slack.circuit.codegen.annotations.CircuitInject
2021
import com.slack.circuit.retained.rememberRetained
2122
import com.slack.circuit.runtime.Navigator
2223
import com.slack.circuit.runtime.presenter.Presenter
24+
import com.slack.circuitx.effects.ImpressionEffect
2325
import dagger.assisted.Assisted
2426
import dagger.assisted.AssistedFactory
2527
import dagger.assisted.AssistedInject
@@ -30,8 +32,14 @@ class RecordDetailPresenter @AssistedInject constructor(
3032
@Assisted private val screen: RecordDetailScreen,
3133
@Assisted private val navigator: Navigator,
3234
private val repository: RecordRepository,
35+
private val analyticsHelper: AnalyticsHelper,
3336
) : Presenter<RecordDetailUiState> {
3437

38+
companion object {
39+
private const val RECORD_DELETE = "record_delete"
40+
private const val RECORD_DELETE_COMPLETE = "record_delete_complete"
41+
}
42+
3543
@Composable
3644
override fun present(): RecordDetailUiState {
3745
val scope = rememberCoroutineScope()
@@ -72,6 +80,7 @@ class RecordDetailPresenter @AssistedInject constructor(
7280
scope.launch {
7381
repository.deleteRecord(readingRecordId = readingRecordId)
7482
.onSuccess {
83+
analyticsHelper.logEvent(RECORD_DELETE_COMPLETE)
7584
onSuccess()
7685
}
7786
.onFailure { exception ->
@@ -146,6 +155,7 @@ class RecordDetailPresenter @AssistedInject constructor(
146155
}
147156

148157
is RecordDetailUiEvent.OnDeleteRecordClick -> {
158+
analyticsHelper.logEvent(RECORD_DELETE)
149159
isRecordMenuBottomSheetVisible = false
150160
isRecordDeleteDialogVisible = true
151161
}
@@ -162,10 +172,14 @@ class RecordDetailPresenter @AssistedInject constructor(
162172
}
163173
}
164174

165-
LaunchedEffect(Unit) {
175+
RememberedEffect(Unit) {
166176
getRecordDetail(screen.recordId)
167177
}
168178

179+
ImpressionEffect {
180+
analyticsHelper.logScreenView(screen.name)
181+
}
182+
169183
return RecordDetailUiState(
170184
uiState = uiState,
171185
recordDetailInfo = recordDetailInfo,

feature/edit/src/main/kotlin/com/ninecraft/booket/feature/edit/record/RecordEditPresenter.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import androidx.compose.runtime.mutableStateOf
99
import androidx.compose.runtime.remember
1010
import androidx.compose.runtime.rememberCoroutineScope
1111
import androidx.compose.runtime.setValue
12+
import com.ninecraft.booket.core.common.analytics.AnalyticsHelper
1213
import com.ninecraft.booket.core.common.utils.handleException
1314
import com.ninecraft.booket.core.data.api.repository.RecordRepository
1415
import com.ninecraft.booket.feature.screens.EmotionEditScreen
@@ -20,6 +21,7 @@ import com.slack.circuit.foundation.rememberAnsweringNavigator
2021
import com.slack.circuit.retained.rememberRetained
2122
import com.slack.circuit.runtime.Navigator
2223
import com.slack.circuit.runtime.presenter.Presenter
24+
import com.slack.circuitx.effects.ImpressionEffect
2325
import dagger.assisted.Assisted
2426
import dagger.assisted.AssistedFactory
2527
import dagger.assisted.AssistedInject
@@ -30,8 +32,15 @@ class RecordEditPresenter @AssistedInject constructor(
3032
@Assisted private val screen: RecordEditScreen,
3133
@Assisted private val navigator: Navigator,
3234
private val repository: RecordRepository,
35+
private val analyticsHelper: AnalyticsHelper,
3336
) : Presenter<RecordEditUiState> {
3437

38+
companion object {
39+
private const val MAX_PAGE = 4032
40+
private const val RECORD_EDIT = "record_edit_save"
41+
private const val RECORD_EDIT_SAVE = "record_edit_save"
42+
}
43+
3544
@Composable
3645
override fun present(): RecordEditUiState {
3746
val scope = rememberCoroutineScope()
@@ -85,6 +94,7 @@ class RecordEditPresenter @AssistedInject constructor(
8594
emotionTags = emotionTags,
8695
review = impression,
8796
).onSuccess {
97+
analyticsHelper.logEvent(RECORD_EDIT_SAVE)
8898
onSuccess()
8999
}.onFailure { exception ->
90100
val handleErrorMessage = { message: String ->
@@ -133,6 +143,10 @@ class RecordEditPresenter @AssistedInject constructor(
133143
}
134144
}
135145

146+
ImpressionEffect {
147+
analyticsHelper.logScreenView(RECORD_EDIT)
148+
}
149+
136150
return RecordEditUiState(
137151
recordInfo = recordInfo,
138152
recordPageState = recordPageState,
@@ -153,8 +167,4 @@ class RecordEditPresenter @AssistedInject constructor(
153167
navigator: Navigator,
154168
): RecordEditPresenter
155169
}
156-
157-
companion object {
158-
const val MAX_PAGE = 4032
159-
}
160170
}

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
package com.ninecraft.booket.feature.home
22

33
import androidx.compose.runtime.Composable
4-
import androidx.compose.runtime.LaunchedEffect
54
import androidx.compose.runtime.getValue
65
import androidx.compose.runtime.mutableStateOf
76
import androidx.compose.runtime.rememberCoroutineScope
87
import androidx.compose.runtime.setValue
8+
import com.ninecraft.booket.core.common.analytics.AnalyticsHelper
99
import com.ninecraft.booket.core.data.api.repository.BookRepository
1010
import com.ninecraft.booket.core.model.RecentBookModel
1111
import com.ninecraft.booket.feature.screens.BookDetailScreen
1212
import com.ninecraft.booket.feature.screens.HomeScreen
1313
import com.ninecraft.booket.feature.screens.RecordScreen
1414
import com.ninecraft.booket.feature.screens.SearchScreen
1515
import com.ninecraft.booket.feature.screens.SettingsScreen
16+
import com.skydoves.compose.effects.RememberedEffect
1617
import com.slack.circuit.codegen.annotations.CircuitInject
1718
import com.slack.circuit.retained.rememberRetained
1819
import com.slack.circuit.runtime.Navigator
1920
import com.slack.circuit.runtime.presenter.Presenter
21+
import com.slack.circuitx.effects.ImpressionEffect
2022
import dagger.assisted.Assisted
2123
import dagger.assisted.AssistedFactory
2224
import dagger.assisted.AssistedInject
@@ -28,6 +30,7 @@ import kotlinx.coroutines.launch
2830
class HomePresenter @AssistedInject constructor(
2931
@Assisted private val navigator: Navigator,
3032
private val repository: BookRepository,
33+
private val analyticsHelper: AnalyticsHelper,
3134
) : Presenter<HomeUiState> {
3235

3336
@Composable
@@ -85,10 +88,14 @@ class HomePresenter @AssistedInject constructor(
8588
}
8689
}
8790

88-
LaunchedEffect(true) {
91+
RememberedEffect(true) {
8992
loadHomeContent()
9093
}
9194

95+
ImpressionEffect {
96+
analyticsHelper.logScreenView(HomeScreen.name)
97+
}
98+
9299
return HomeUiState(
93100
uiState = uiState,
94101
recentBooks = recentBooks,

0 commit comments

Comments
 (0)