Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import com.eatssu.android.presentation.mypage.userinfo.UserInfoActivity
import com.eatssu.android.presentation.util.showInfoToast
import com.eatssu.android.presentation.util.showToast
import com.eatssu.android.presentation.util.startActivity
import com.eatssu.common.analytics.MapAnalyticsEvent
import com.eatssu.common.analytics.MyPageAnalyticsEvent
import com.eatssu.common.UiEvent
import com.eatssu.common.UiState
import com.eatssu.common.enums.ScreenId
Expand Down Expand Up @@ -85,6 +87,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(
}

R.id.map_menu -> {
analyticsTracker.track(MapAnalyticsEvent.EntryClicked)
navController.navigate(R.id.mapFragment)
true
}
Expand All @@ -95,6 +98,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(
}

R.id.mypage_menu -> {
analyticsTracker.track(MyPageAnalyticsEvent.MenuClicked)
navController.navigate(R.id.myPageFragment)
true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.lifecycle.LifecycleCoroutineScope
import com.eatssu.android.R
import com.eatssu.android.data.local.AppFeatureDataStore
import com.eatssu.android.domain.usecase.user.GetUserCollegeDepartmentUseCase
import com.eatssu.android.presentation.mypage.terms.WebViewActivity
import com.eatssu.android.presentation.util.openInBrowser
import com.eatssu.common.analytics.AnalyticsTracker
import com.eatssu.common.analytics.AnyoneButMeAnalyticsEvent
import com.eatssu.common.analytics.PopupAnalyticsEvent
import com.eatssu.common.enums.ScreenId
import com.eatssu.design_system.theme.EatssuTheme
import dagger.hilt.android.qualifiers.ActivityContext
Expand All @@ -22,6 +26,8 @@ import javax.inject.Inject
class AnyoneButMeEventPopupController @Inject constructor(
@ActivityContext private val context: Context,
private val appFeatureDataStore: AppFeatureDataStore,
private val getUserCollegeDepartmentUseCase: GetUserCollegeDepartmentUseCase,
private val analyticsTracker: AnalyticsTracker,
) {
private lateinit var composeView: ComposeView
private lateinit var lifecycleScope: LifecycleCoroutineScope
Expand Down Expand Up @@ -49,10 +55,10 @@ class AnyoneButMeEventPopupController @Inject constructor(
EatssuTheme {
if (isPopupVisible.value) {
AnyoneButMeEventDialog(
onDismiss = ::hide,
onDismiss = ::closeByUser,
onDismissForever = ::dismissForever,
onInstagramClick = ::openInstagram,
onAnyoneButMeClick = ::openAnyoneButMePage
onAnyoneButMeClick = { openAnyoneButMePage(fromPopup = true) }
)
}
}
Expand All @@ -71,13 +77,18 @@ class AnyoneButMeEventPopupController @Inject constructor(
}

private fun dismissForever() {
trackPopupAction(PopupAnalyticsEvent.Action.NOT_SHOW_AGAIN)
hide()
lifecycleScope.launch {
appFeatureDataStore.setAnyoneButMeEventPopupDismissed(true)
}
}

fun openAnyoneButMePage() {
fun openAnyoneButMePage(fromPopup: Boolean = false) {
if (fromPopup) {
trackPopupAction(PopupAnalyticsEvent.Action.CLICK_POPUP_IMAGE)
}
trackAnyoneButMeClicked()
hide()
context.startActivity(
Intent(context, WebViewActivity::class.java).apply {
Expand All @@ -93,10 +104,32 @@ class AnyoneButMeEventPopupController @Inject constructor(
}

private fun openInstagram() {
trackPopupAction(PopupAnalyticsEvent.Action.GO_INSTA)
hide()
context.openInBrowser(context.getString(R.string.eatssu_event_instagram_url))
}

private fun closeByUser() {
trackPopupAction(PopupAnalyticsEvent.Action.CLOSE)
hide()
}

private fun trackPopupAction(action: PopupAnalyticsEvent.Action) {
analyticsTracker.track(PopupAnalyticsEvent.AnyoneButMe(action))
}

private fun trackAnyoneButMeClicked() {
lifecycleScope.launch {
val userInfo = getUserCollegeDepartmentUseCase()
analyticsTracker.track(
AnyoneButMeAnalyticsEvent.Clicked(
college = userInfo.userCollege.collegeId.toLong(),
major = userInfo.userDepartment.departmentId.toLong(),
),
)
}
}

private fun hide() {
canAutoShowOnLaunch = false
isPopupVisible.value = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.eatssu.android.presentation.base.BaseActivity
import com.eatssu.android.presentation.util.showErrorToast
import com.eatssu.android.presentation.util.showToast
import com.eatssu.android.presentation.util.startActivity
import com.eatssu.common.analytics.LoginAnalyticsEvent
import com.eatssu.common.UiEvent
import com.eatssu.common.UiState
import com.eatssu.common.enums.ScreenId
Expand Down Expand Up @@ -52,6 +53,7 @@ class LoginActivity :
}

binding.ibKakaoLogin.setOnClickListener {
analyticsTracker.track(LoginAnalyticsEvent.Clicked(LoginAnalyticsEvent.Method.KAKAO))
handleKakaoLogin()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.eatssu.android.domain.usecase.auth.LoginUseCase
import com.eatssu.android.domain.usecase.auth.SetAccessTokenUseCase
import com.eatssu.android.domain.usecase.auth.SetRefreshTokenUseCase
import com.eatssu.android.domain.usecase.user.SetUserEmailUseCase
import com.eatssu.common.analytics.AnalyticsTracker
import com.eatssu.common.analytics.LoginAnalyticsEvent
import com.eatssu.common.UiEvent
import com.eatssu.common.UiState
import com.eatssu.common.UiText
Expand All @@ -30,6 +32,7 @@ class LoginViewModel @Inject constructor(
private val setAccessTokenUseCase: SetAccessTokenUseCase,
private val setRefreshTokenUseCase: SetRefreshTokenUseCase,
private val setUserEmailUseCase: SetUserEmailUseCase,
private val analyticsTracker: AnalyticsTracker,
private val analyticsIdentityManager: AnalyticsIdentityManager,
) : ViewModel() {

Expand Down Expand Up @@ -58,6 +61,7 @@ class LoginViewModel @Inject constructor(
setRefreshTokenUseCase(token.refreshToken)
setUserEmailUseCase(email)
analyticsIdentityManager.identifyUser(email = email)
analyticsTracker.track(LoginAnalyticsEvent.Completed(LoginAnalyticsEvent.Method.KAKAO))

_uiState.value = UiState.Success(LoginState.LoginSuccess)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ class MapViewModel @Inject constructor(
when (filter) {
FilterType.All -> {
loadPartnerships()
analyticsTracker.track(MapAnalyticsEvent.AllClicked)
}

FilterType.Mine -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.eatssu.android.presentation.widget
import android.content.Context
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import com.eatssu.android.domain.usecase.widget.LoadRestaurantByFileKeyUseCase
import com.eatssu.android.presentation.widget.ui.MealWidget
import com.eatssu.common.analytics.AnalyticsTracker
import com.eatssu.common.analytics.WidgetAnalyticsEvent
Expand All @@ -17,6 +18,9 @@ class MealWidgetReceiver : GlanceAppWidgetReceiver() {
@Inject
lateinit var analyticsTracker: AnalyticsTracker

@Inject
lateinit var loadRestaurantByFileKeyUseCase: LoadRestaurantByFileKeyUseCase

override val glanceAppWidget: GlanceAppWidget
get() = MealWidget()

Expand All @@ -32,15 +36,17 @@ class MealWidgetReceiver : GlanceAppWidgetReceiver() {
private fun cleanupWidgetDataStore(context: Context, appWidgetId: Int) {
try {
runBlocking {
val widgetFileKey = "appWidget-$appWidgetId"
val filename = "appWidgetLayout-${appWidgetId}"
val dataStoreFile = File(context.filesDir, "datastore/$filename")
val restaurant = loadRestaurantByFileKeyUseCase(widgetFileKey)

if (dataStoreFile.exists()) {
dataStoreFile.delete()
Timber.d("Deleted DataStore file for widget $appWidgetId")
}

analyticsTracker.track(WidgetAnalyticsEvent.Removed())
analyticsTracker.track(WidgetAnalyticsEvent.Removed(restaurant))

}
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import androidx.glance.GlanceId
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.lifecycle.lifecycleScope
import com.eatssu.android.analytics.ProvideAnalyticsTracker
import com.eatssu.android.domain.usecase.widget.LoadRestaurantByFileKeyUseCase
import com.eatssu.android.domain.usecase.widget.SaveRestaurantByFileKeyUseCase
import com.eatssu.android.presentation.widget.MealWorker
import com.eatssu.common.analytics.AnalyticsTracker
import com.eatssu.common.analytics.WidgetAnalyticsEvent
import com.eatssu.common.enums.Restaurant
import com.eatssu.design_system.theme.EatssuTheme
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -32,6 +34,9 @@ class WidgetSettingActivity : ComponentActivity() {
@Inject
lateinit var saveRestaurantByFileKeyUseCase: SaveRestaurantByFileKeyUseCase

@Inject
lateinit var loadRestaurantByFileKeyUseCase: LoadRestaurantByFileKeyUseCase

@Inject
lateinit var analyticsTracker: AnalyticsTracker

Expand All @@ -46,6 +51,7 @@ class WidgetSettingActivity : ComponentActivity() {
} // 변동 식당만 불러옵니다. 하드코딩 x

var selectedRestaurant by rememberSaveable { mutableStateOf(restaurantOptions[0]) }
var previousRestaurant by remember { mutableStateOf<Restaurant?>(null) }

val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
Expand All @@ -54,12 +60,22 @@ class WidgetSettingActivity : ComponentActivity() {
var glanceId by remember { mutableStateOf<GlanceId?>(null) }
val context = LocalContext.current
LaunchedEffect(appWidgetId) {
glanceId =
if (appWidgetId != null && appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
GlanceAppWidgetManager(context).getGlanceIdBy(appWidgetId)
glanceId = if (appWidgetId != null && appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
GlanceAppWidgetManager(context).getGlanceIdBy(appWidgetId)
} else {
null
}

previousRestaurant =
if (appWidgetId != null && appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
loadRestaurantByFileKeyUseCase("appWidget-$appWidgetId")
} else {
null
}

previousRestaurant?.let { savedRestaurant ->
selectedRestaurant = getString(savedRestaurant.displayNameResId)
}
}

WidgetSettingScreen(
Expand All @@ -75,12 +91,27 @@ class WidgetSettingActivity : ComponentActivity() {
}

lifecycleScope.launch {
val widgetFileKey = "appWidget-$appWidgetId"

saveRestaurantByFileKeyUseCase(
"appWidget-${appWidgetId}",
widgetFileKey,
selectedRestaurantValue
)

when (val before = previousRestaurant) {
null -> analyticsTracker.track(WidgetAnalyticsEvent.Added(selectedRestaurantValue))
selectedRestaurantValue ->
Unit

else ->
analyticsTracker.track(
WidgetAnalyticsEvent.Changed(
restaurantBefore = before,
restaurantAfter = selectedRestaurantValue,
),
)
}

// 위젯 업데이트
glanceId?.let {
MealWidget().update(this@WidgetSettingActivity, it)
Expand All @@ -90,17 +121,16 @@ class WidgetSettingActivity : ComponentActivity() {
MealWorker.enqueue(this@WidgetSettingActivity)

Timber.d("선택하기 버튼으로 저장: $selectedRestaurantValue for glanceId: $glanceId")
}

// 결과 설정
val resultIntent = Intent().apply {
putExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId ?: AppWidgetManager.INVALID_APPWIDGET_ID
)
val resultIntent = Intent().apply {
putExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId ?: AppWidgetManager.INVALID_APPWIDGET_ID
)
}
setResult(RESULT_OK, resultIntent)
finish()
}
setResult(RESULT_OK, resultIntent)
finish()
},
onBack = { finish() }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.eatssu.android.R
import com.eatssu.android.analytics.LocalAnalyticsTracker
import com.eatssu.common.analytics.WidgetAnalyticsEvent
import com.eatssu.android.presentation.util.asString
import com.eatssu.common.enums.Restaurant
import com.eatssu.design_system.component.EatSsuButton
Expand All @@ -34,8 +32,6 @@ fun WidgetSettingScreen(
onConfirm: (Restaurant) -> Unit = {},
onBack: () -> Unit = {} // 뒤로가기 동작을 위한 람다 추가
) {
val analyticsTracker = LocalAnalyticsTracker.current

// onClick 람다에서 LocalContext 접근이 불가하므로 Composable 레벨에서 미리 매핑 생성
val restaurantDisplayNameMap = Restaurant.getVariableRestaurantList()
.associateBy { it.toUiText().asString() }
Expand Down Expand Up @@ -77,7 +73,6 @@ fun WidgetSettingScreen(
?: Restaurant.HAKSIK

onConfirm(selectedRestaurantEnum)
analyticsTracker.track(WidgetAnalyticsEvent.Added(selectedRestaurantEnum))
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DefaultAnalyticsTrackerTest {
val second = FakeAnalyticsTracker(id = "duplicate")
val analyticsTracker = DefaultAnalyticsTracker(setOf(first, second))

analyticsTracker.track(MapAnalyticsEvent.AllClicked)
analyticsTracker.track(MapAnalyticsEvent.EntryClicked)

assertEquals(1, first.events.size + second.events.size)
}
Expand All @@ -57,7 +57,7 @@ class DefaultAnalyticsTrackerTest {
val failingTracker = FakeAnalyticsTracker(id = "firebase", failOnTrack = true)
val healthyTracker = FakeAnalyticsTracker(id = "posthog")
val analyticsTracker = DefaultAnalyticsTracker(setOf(failingTracker, healthyTracker))
val event = MapAnalyticsEvent.AllClicked
val event = MapAnalyticsEvent.EntryClicked

analyticsTracker.track(event)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class FirebaseAnalyticsTrackerTest {
mapOf(
"rating" to 5L,
"likes" to 2L,
"photo_attached" to true,
"photo_attached" to 1L,
),
payload.properties,
)
Expand Down
Loading
Loading