diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 547e7f99b..ae2585730 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -55,9 +55,6 @@ android { isShrinkResources = false isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - - var shrinkResources = false - var minifyEnabled = false } debug { @@ -114,6 +111,7 @@ android { dependencies { implementation(project(":core:design-system")) + implementation(project(":core:common")) implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) @@ -200,7 +198,6 @@ dependencies { implementation(libs.androidx.compose.ui.graphics) implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.compose.material3) -// androidTestImplementation(libs.androidx.compose.ui.test.junit4) implementation(libs.compose.theme.adapter) implementation(libs.accompanist.appcompat.theme) androidTestImplementation(libs.androidx.compose.bom) diff --git a/app/src/main/java/com/eatssu/android/alarm/NotificationReceiver.kt b/app/src/main/java/com/eatssu/android/alarm/NotificationReceiver.kt index e1dfc58ea..328646856 100644 --- a/app/src/main/java/com/eatssu/android/alarm/NotificationReceiver.kt +++ b/app/src/main/java/com/eatssu/android/alarm/NotificationReceiver.kt @@ -10,7 +10,7 @@ import android.os.Build import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import com.eatssu.android.R -import com.eatssu.android.presentation.cafeteria.CafeteriaFragment +import com.eatssu.android.presentation.login.IntroActivity import java.time.DayOfWeek import java.time.LocalDateTime @@ -44,14 +44,14 @@ class NotificationReceiver : BroadcastReceiver() { } - val intent = Intent(context, CafeteriaFragment::class.java).apply { + val intent = Intent(context, IntroActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val pendingIntent = PendingIntent.getActivity( context, 0, - intent, + intent.putExtra("launch_path", "notification"), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) diff --git a/app/src/main/java/com/eatssu/android/data/enums/Provider.kt b/app/src/main/java/com/eatssu/android/data/enums/Provider.kt deleted file mode 100644 index 4275d2f9b..000000000 --- a/app/src/main/java/com/eatssu/android/data/enums/Provider.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.eatssu.android.data.enums - -enum class Provider { - KAKAO -} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/enums/ReportType.kt b/app/src/main/java/com/eatssu/android/data/enums/ReportType.kt deleted file mode 100644 index 15483de91..000000000 --- a/app/src/main/java/com/eatssu/android/data/enums/ReportType.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.eatssu.android.data.enums - -import com.eatssu.android.R - -enum class ReportType(val description: Int) { - NO_ASSOCIATE_CONTENT(R.string.report1), - IMPROPER_CONTENT(R.string.report2), - IMPROPER_ADVERTISEMENT(R.string.report3), - COPY(R.string.report4), - COPYRIGHT(R.string.report5), - EXTRA(R.string.report6) -} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/enums/Restaurant.kt b/app/src/main/java/com/eatssu/android/data/enums/Restaurant.kt deleted file mode 100644 index 693fcf065..000000000 --- a/app/src/main/java/com/eatssu/android/data/enums/Restaurant.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.eatssu.android.data.enums - - - -enum class Restaurant(val displayName: String, val menuType: MenuType) { - HAKSIK("학생 식당", MenuType.VARIABLE), - DODAM("도담 식당", MenuType.VARIABLE), - DORMITORY("기숙사 식당", MenuType.VARIABLE), - FACULTY("FACULTY (교직원 전용)", MenuType.VARIABLE), - FOOD_COURT("푸드 코트", MenuType.FIXED), - SNACK_CORNER("스낵 코너", MenuType.FIXED), - THE_KITCHEN("더 키친", MenuType.FIXED); - - companion object { - - fun getVariableRestaurantList(): List { - return entries.filter { it.menuType == MenuType.VARIABLE } - } - - fun fromRestaurantEnumName(enumName: String): String { - return entries.find { it.name == enumName }?.displayName ?: "" - } - - fun fromDisplayName(name: String): String = - entries.find { it.displayName == name }?.name ?: error("Unknown display name: $name") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/enums/Time.kt b/app/src/main/java/com/eatssu/android/data/enums/Time.kt deleted file mode 100644 index 74f1dc8de..000000000 --- a/app/src/main/java/com/eatssu/android/data/enums/Time.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.eatssu.android.data.enums - -enum class Time(val displayName: String) { - MORNING("조식"), - LUNCH("중식"), - DINNER("석식"); - - companion object { - fun fromTimeEnumName(enumName: String): String { - return Time.values().find { it.name == enumName }?.displayName ?: "" - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/repository/FirebaseRemoteConfigRepository.kt b/app/src/main/java/com/eatssu/android/data/repository/FirebaseRemoteConfigRepository.kt index 3c6be74b9..f979c9063 100644 --- a/app/src/main/java/com/eatssu/android/data/repository/FirebaseRemoteConfigRepository.kt +++ b/app/src/main/java/com/eatssu/android/data/repository/FirebaseRemoteConfigRepository.kt @@ -1,8 +1,8 @@ package com.eatssu.android.data.repository import com.eatssu.android.R -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.model.RestaurantInfo +import com.eatssu.common.enums.Restaurant import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings import org.json.JSONArray diff --git a/app/src/main/java/com/eatssu/android/data/repository/MealRepositoryImpl.kt b/app/src/main/java/com/eatssu/android/data/repository/MealRepositoryImpl.kt index 660e76e93..9202e2e0b 100644 --- a/app/src/main/java/com/eatssu/android/data/repository/MealRepositoryImpl.kt +++ b/app/src/main/java/com/eatssu/android/data/repository/MealRepositoryImpl.kt @@ -36,7 +36,6 @@ class MealRepositoryImpl @Inject constructor( } } - override suspend fun getMenuInfoByMealId(mealId: Long): Flow> = flow { emit(mealService.getMenuInfoByMealId(mealId)) diff --git a/app/src/main/java/com/eatssu/android/data/repository/WidgetPreferencesRepository.kt b/app/src/main/java/com/eatssu/android/data/repository/WidgetPreferencesRepository.kt index a6fe114c7..e68578bbc 100644 --- a/app/src/main/java/com/eatssu/android/data/repository/WidgetPreferencesRepository.kt +++ b/app/src/main/java/com/eatssu/android/data/repository/WidgetPreferencesRepository.kt @@ -6,7 +6,7 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore -import com.eatssu.android.data.enums.Restaurant +import com.eatssu.common.enums.Restaurant import kotlinx.coroutines.flow.first import timber.log.Timber import javax.inject.Inject @@ -20,9 +20,9 @@ class WidgetPreferencesRepository @Inject constructor( private fun fileKeyRestaurantKey(fileKey: String) = stringPreferencesKey("widget_restaurant_by_fileKey_$fileKey") - suspend fun saveRestaurantByFileKey(fileKey: String, restaurant: String) { + suspend fun saveRestaurantByFileKey(fileKey: String, restaurant: Restaurant) { context.widgetPrefsDataStore.edit { prefs -> - prefs[fileKeyRestaurantKey(fileKey)] = restaurant + prefs[fileKeyRestaurantKey(fileKey)] = restaurant.name } Timber.d("saveRestaurantByFileKey 호출됨: fileKey='$fileKey', restaurant='$restaurant'") } diff --git a/app/src/main/java/com/eatssu/android/domain/model/RestaurantInfo.kt b/app/src/main/java/com/eatssu/android/domain/model/RestaurantInfo.kt index 4280743f3..72d3b416b 100644 --- a/app/src/main/java/com/eatssu/android/domain/model/RestaurantInfo.kt +++ b/app/src/main/java/com/eatssu/android/domain/model/RestaurantInfo.kt @@ -1,6 +1,6 @@ package com.eatssu.android.domain.model -import com.eatssu.android.data.enums.Restaurant +import com.eatssu.common.enums.Restaurant data class RestaurantInfo( val enum: Restaurant, diff --git a/app/src/main/java/com/eatssu/android/domain/model/Section.kt b/app/src/main/java/com/eatssu/android/domain/model/Section.kt index 6a051b4ec..f22398cc2 100644 --- a/app/src/main/java/com/eatssu/android/domain/model/Section.kt +++ b/app/src/main/java/com/eatssu/android/domain/model/Section.kt @@ -1,7 +1,7 @@ package com.eatssu.android.domain.model -import com.eatssu.android.data.enums.MenuType -import com.eatssu.android.data.enums.Restaurant +import com.eatssu.common.enums.MenuType +import com.eatssu.common.enums.Restaurant data class Section( val menuType: MenuType, diff --git a/app/src/main/java/com/eatssu/android/domain/model/WidgetMealInfo.kt b/app/src/main/java/com/eatssu/android/domain/model/WidgetMealInfo.kt index 8eb78c9cf..f49cc3d5a 100644 --- a/app/src/main/java/com/eatssu/android/domain/model/WidgetMealInfo.kt +++ b/app/src/main/java/com/eatssu/android/domain/model/WidgetMealInfo.kt @@ -1,6 +1,6 @@ package com.eatssu.android.domain.model -import com.eatssu.android.data.enums.Restaurant +import com.eatssu.common.enums.Restaurant sealed interface WidgetMealInfo { diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMealReviewListUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMealReviewListUseCase.kt index 157b36c6b..d8100ea78 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMealReviewListUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMealReviewListUseCase.kt @@ -2,8 +2,8 @@ package com.eatssu.android.domain.usecase.review import com.eatssu.android.data.dto.response.BaseResponse import com.eatssu.android.data.dto.response.GetReviewListResponse -import com.eatssu.android.data.enums.MenuType import com.eatssu.android.domain.repository.ReviewRepository +import com.eatssu.common.enums.MenuType import kotlinx.coroutines.flow.Flow import javax.inject.Inject diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMenuReviewListUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMenuReviewListUseCase.kt index 5ed6df593..a36d6ae5e 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMenuReviewListUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/review/GetMenuReviewListUseCase.kt @@ -2,8 +2,8 @@ package com.eatssu.android.domain.usecase.review import com.eatssu.android.data.dto.response.BaseResponse import com.eatssu.android.data.dto.response.GetReviewListResponse -import com.eatssu.android.data.enums.MenuType import com.eatssu.android.domain.repository.ReviewRepository +import com.eatssu.common.enums.MenuType import kotlinx.coroutines.flow.Flow import javax.inject.Inject diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/widget/GetTodayMealUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/widget/GetTodayMealUseCase.kt index bb8d0d28f..e202b4c5e 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/widget/GetTodayMealUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/widget/GetTodayMealUseCase.kt @@ -1,9 +1,9 @@ package com.eatssu.android.domain.usecase.widget -import com.eatssu.android.data.enums.Restaurant -import com.eatssu.android.data.enums.Time import com.eatssu.android.domain.repository.MealRepository import com.eatssu.android.presentation.widget.WidgetMealList +import com.eatssu.common.enums.Restaurant +import com.eatssu.common.enums.Time import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import timber.log.Timber diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/widget/LoadRestaurantByFileKeyUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/widget/LoadRestaurantByFileKeyUseCase.kt index 9f7169fa6..e5ea1e391 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/widget/LoadRestaurantByFileKeyUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/widget/LoadRestaurantByFileKeyUseCase.kt @@ -1,7 +1,7 @@ package com.eatssu.android.domain.usecase.widget -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.data.repository.WidgetPreferencesRepository +import com.eatssu.common.enums.Restaurant import javax.inject.Inject class LoadRestaurantByFileKeyUseCase @Inject constructor( diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/widget/SaveRestaurantByFileKeyUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/widget/SaveRestaurantByFileKeyUseCase.kt index fe78e8c89..abb852f67 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/widget/SaveRestaurantByFileKeyUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/widget/SaveRestaurantByFileKeyUseCase.kt @@ -1,12 +1,13 @@ package com.eatssu.android.domain.usecase.widget import com.eatssu.android.data.repository.WidgetPreferencesRepository +import com.eatssu.common.enums.Restaurant import javax.inject.Inject class SaveRestaurantByFileKeyUseCase @Inject constructor( private val widgetPrefsRepository: WidgetPreferencesRepository ) { - suspend operator fun invoke(fileKey: String, restaurantDisplayName: String) { - widgetPrefsRepository.saveRestaurantByFileKey(fileKey, restaurantDisplayName) + suspend operator fun invoke(fileKey: String, restaurant: Restaurant) { + widgetPrefsRepository.saveRestaurantByFileKey(fileKey, restaurant) } } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaFragment.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaFragment.kt index 88f85cbf9..7f1ef269e 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaFragment.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaFragment.kt @@ -11,13 +11,15 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.eatssu.android.databinding.FragmentCafeteriaBinding -import com.eatssu.android.presentation.base.BaseFragment import com.eatssu.android.presentation.MainViewModel +import com.eatssu.android.presentation.base.BaseFragment import com.eatssu.android.presentation.cafeteria.calendar.CalendarAdapter import com.eatssu.android.presentation.cafeteria.calendar.CalendarAdapter.OnItemListener import com.eatssu.android.presentation.util.CalendarUtil import com.eatssu.android.presentation.util.CalendarUtil.daysInWeekArray import com.eatssu.android.presentation.util.CalendarUtil.monthYearFromDate +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.Time import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint @@ -50,6 +52,9 @@ class CafeteriaFragment : BaseFragment(), OnItemListen val tabTitles = listOf("아침", "점심", "저녁") TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = tabTitles[position] }.attach() + // ViewPager 페이지 변경 감지 + setupViewPagerPageChangeListener(viewPager) + initWidgets() CalendarUtil.selectedDate = LocalDate.now() mainViewModel.setData(CalendarUtil.selectedDate) @@ -57,6 +62,23 @@ class CafeteriaFragment : BaseFragment(), OnItemListen setCalendarWeekClickListener() } + private fun setupViewPagerPageChangeListener(viewPager: ViewPager2) { + viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + + // 페이지 변경 시 이벤트 로깅 + val time = when (position) { + 0 -> Time.MORNING + 1 -> Time.LUNCH + 2 -> Time.DINNER + else -> Time.LUNCH // 기본값 + } + EventLogger.selectMealTime(time) + } + }) + } + private fun initWidgets() { calendarRecyclerView = binding.weekRecycler monthYearText = binding.monthYearTV @@ -94,5 +116,6 @@ class CafeteriaFragment : BaseFragment(), OnItemListen mainViewModel.setData(date) mainPosition = position setWeekView() + EventLogger.selectDay(date.dayOfWeek.name) } } diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaViewPagerAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaViewPagerAdapter.kt index ef7279195..392ab8f84 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaViewPagerAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/CafeteriaViewPagerAdapter.kt @@ -5,8 +5,8 @@ import androidx.annotation.RequiresApi import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter -import com.eatssu.android.data.enums.Time import com.eatssu.android.presentation.cafeteria.menu.MenuFragment +import com.eatssu.common.enums.Time import java.time.LocalTime class CafeteriaViewPagerAdapter(fragmentActivity: FragmentActivity) : diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoBottomSheetFragment.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoBottomSheetFragment.kt index e73a3c94e..8a5a02a29 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoBottomSheetFragment.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoBottomSheetFragment.kt @@ -6,8 +6,9 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.activityViewModels import com.bumptech.glide.Glide -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.databinding.FragmentBottomsheetInfoBinding +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.Restaurant import com.google.android.material.bottomsheet.BottomSheetDialogFragment import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -36,7 +37,9 @@ class InfoBottomSheetFragment : BottomSheetDialogFragment() { val restaurantType = enumValues().find { it.name == name } ?: Restaurant.HAKSIK Timber.d("onViewCreated: $name $restaurantType") - binding.tvName.text = restaurantType.displayName + EventLogger.clickRestaurantInfo(restaurantType) + + binding.tvName.text = restaurantType.korean CoroutineScope(Dispatchers.Main).launch { infoViewModel.infoList.collect { diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoViewModel.kt index 64e1cc665..bba46c978 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoViewModel.kt @@ -1,9 +1,9 @@ package com.eatssu.android.presentation.cafeteria.info import androidx.lifecycle.ViewModel -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.data.repository.FirebaseRemoteConfigRepository import com.eatssu.android.domain.model.RestaurantInfo +import com.eatssu.common.enums.Restaurant import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuAdapter.kt index 0fa1932c6..a4e3760ff 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuAdapter.kt @@ -39,14 +39,14 @@ class MenuAdapter( Log.d("MenuAdapter", "bind: ${sectionModel.cafeteria}") } - binding.tvCafeteria.text = sectionModel.cafeteria.displayName + binding.tvCafeteria.text = sectionModel.cafeteria.korean binding.tvCafeteriaLocation.text = sectionModel.cafeteriaLocation binding.rvMenu.apply { setHasFixedSize(true) layoutManager = LinearLayoutManager(binding.root.context) adapter = sectionModel.menuList?.let { - MenuSubAdapter(it, sectionModel.cafeteria.menuType) + MenuSubAdapter(it, sectionModel.cafeteria) } } } diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuFragment.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuFragment.kt index 55a75775d..d16a0b68d 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuFragment.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuFragment.kt @@ -16,14 +16,14 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.LinearLayoutManager import com.eatssu.android.data.dto.response.mapFixedMenuResponseToMenu import com.eatssu.android.data.dto.response.mapTodayMenuResponseToMenu -import com.eatssu.android.data.enums.MenuType -import com.eatssu.android.data.enums.Restaurant -import com.eatssu.android.data.enums.Time import com.eatssu.android.databinding.FragmentMenuBinding import com.eatssu.android.domain.model.Section +import com.eatssu.android.presentation.MainViewModel import com.eatssu.android.presentation.UiState import com.eatssu.android.presentation.cafeteria.info.InfoViewModel -import com.eatssu.android.presentation.MainViewModel +import com.eatssu.common.enums.MenuType +import com.eatssu.common.enums.Restaurant +import com.eatssu.common.enums.Time import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import java.time.DayOfWeek @@ -118,7 +118,8 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.HAKSIK } if (result.isNotEmpty()) { totalMenuList.add( - Section(MenuType.VARIABLE, Restaurant.HAKSIK, + Section( + MenuType.VARIABLE, Restaurant.HAKSIK, result.mapTodayMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.HAKSIK)?.location ?: "" ) @@ -136,7 +137,8 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.DODAM } if (result.isNotEmpty()) { totalMenuList.add( - Section(MenuType.VARIABLE, Restaurant.DODAM, + Section( + MenuType.VARIABLE, Restaurant.DODAM, result.mapTodayMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.DODAM)?.location ?: "" ) @@ -154,7 +156,9 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.DORMITORY } if (result.isNotEmpty()) { totalMenuList.add( - Section(MenuType.VARIABLE, Restaurant.DORMITORY, + Section( + MenuType.VARIABLE, + Restaurant.DORMITORY, result.mapTodayMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.DORMITORY)?.location ?: "" ) @@ -172,7 +176,8 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.FACULTY } if (result.isNotEmpty()) { totalMenuList.add( - Section(MenuType.VARIABLE, Restaurant.FACULTY, + Section( + MenuType.VARIABLE, Restaurant.FACULTY, result.mapTodayMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.FACULTY)?.location ?: "" ) @@ -192,7 +197,9 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.FOOD_COURT } if (result.mapFixedMenuResponseToMenu().isNotEmpty()) { totalMenuList.add( - Section(MenuType.FIXED, Restaurant.FOOD_COURT, + Section( + MenuType.FIXED, + Restaurant.FOOD_COURT, result.mapFixedMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.FOOD_COURT)?.location ?: "" ) @@ -210,7 +217,9 @@ class MenuFragment : Fragment() { totalMenuList.removeAll { it.cafeteria == Restaurant.SNACK_CORNER } if (result.mapFixedMenuResponseToMenu().isNotEmpty()) { totalMenuList.add( - Section(MenuType.FIXED, Restaurant.SNACK_CORNER, + Section( + MenuType.FIXED, + Restaurant.SNACK_CORNER, result.mapFixedMenuResponseToMenu(), infoViewModel.getRestaurantInfo(Restaurant.SNACK_CORNER)?.location ?: "" ) diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuSubAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuSubAdapter.kt index 72984efd5..ef2092677 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuSubAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuSubAdapter.kt @@ -6,15 +6,17 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView -import com.eatssu.android.data.enums.MenuType import com.eatssu.android.databinding.ItemMenuBinding import com.eatssu.android.domain.model.Menu import com.eatssu.android.presentation.cafeteria.review.list.ReviewActivity +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.MenuType +import com.eatssu.common.enums.Restaurant class MenuSubAdapter( private val dataList: List, - private val menuType: MenuType + private val restaurant: Restaurant, ) : RecyclerView.Adapter() { @@ -47,7 +49,7 @@ class MenuSubAdapter( holder.itemView.setOnClickListener { val intent = Intent(holder.itemView.context, ReviewActivity::class.java) - when (menuType) { + when (restaurant.menuType) { MenuType.FIXED -> { Log.d("SubMenuAdapter", "고정메뉴${dataList[position].name}") intent.putExtra("itemId", dataList[position].id) @@ -63,10 +65,8 @@ class MenuSubAdapter( } } ContextCompat.startActivity(holder.itemView.context, intent, null) - + EventLogger.clickMenu(restaurant) } - - } override fun getItemCount(): Int = dataList.size diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuViewModel.kt index 1e8fa3ed7..9879f9990 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/menu/MenuViewModel.kt @@ -5,12 +5,12 @@ import androidx.lifecycle.viewModelScope import com.eatssu.android.data.dto.response.BaseResponse import com.eatssu.android.data.dto.response.GetFixedMenuResponse import com.eatssu.android.data.dto.response.GetMealResponse -import com.eatssu.android.data.enums.Restaurant -import com.eatssu.android.data.enums.Time import com.eatssu.android.data.service.MealService import com.eatssu.android.data.service.MenuService import com.eatssu.android.domain.model.MenuMini import com.eatssu.android.presentation.UiState +import com.eatssu.common.enums.Restaurant +import com.eatssu.common.enums.Time import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewActivity.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewActivity.kt index b028a0960..1bc349e9f 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewActivity.kt @@ -8,14 +8,15 @@ import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.eatssu.android.R -import com.eatssu.android.data.enums.MenuType import com.eatssu.android.databinding.ActivityReviewBinding import com.eatssu.android.domain.model.Review import com.eatssu.android.presentation.base.BaseActivity -import com.eatssu.android.presentation.common.MyReviewBottomSheetFragment -import com.eatssu.android.presentation.common.OthersBottomSheetFragment import com.eatssu.android.presentation.cafeteria.review.write.ReviewWriteRateActivity import com.eatssu.android.presentation.cafeteria.review.write.menu.ReviewWriteMenuActivity +import com.eatssu.android.presentation.common.MyReviewBottomSheetFragment +import com.eatssu.android.presentation.common.OthersBottomSheetFragment +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.MenuType import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -153,6 +154,7 @@ class ReviewActivity : intent.putExtra("itemName", itemName) intent.putExtra("menuType", menuType) startActivity(intent) + EventLogger.writeReview() } } @@ -162,6 +164,7 @@ class ReviewActivity : intent.putExtra("itemId", itemId) intent.putExtra("menuType", menuType) startActivity(intent) + EventLogger.writeReview() } } diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewViewModel.kt index 01e136aea..3aca37e79 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/list/ReviewViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.eatssu.android.data.dto.response.asReviewInfo import com.eatssu.android.data.dto.response.toReviewList -import com.eatssu.android.data.enums.MenuType import com.eatssu.android.domain.model.Review import com.eatssu.android.domain.model.ReviewInfo import com.eatssu.android.domain.usecase.review.DeleteReviewUseCase @@ -12,6 +11,7 @@ import com.eatssu.android.domain.usecase.review.GetMealReviewInfoUseCase import com.eatssu.android.domain.usecase.review.GetMealReviewListUseCase import com.eatssu.android.domain.usecase.review.GetMenuReviewInfoUseCase import com.eatssu.android.domain.usecase.review.GetMenuReviewListUseCase +import com.eatssu.common.enums.MenuType import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/report/ReportActivity.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/report/ReportActivity.kt index 7c3c97396..128191ec6 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/report/ReportActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/report/ReportActivity.kt @@ -5,10 +5,10 @@ import android.text.Editable import android.text.TextWatcher import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope -import com.eatssu.android.data.enums.ReportType import com.eatssu.android.databinding.ActivityReportBinding import com.eatssu.android.presentation.base.BaseActivity import com.eatssu.android.presentation.util.showToast +import com.eatssu.common.enums.ReportType import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -57,7 +57,7 @@ class ReportActivity : BaseActivity(ActivityReportBinding content = if (selectedReportType == ReportType.EXTRA) { inputText } else { - getString(selectedReportType.description) + selectedReportType.description } reportViewModel.postData(reviewId, reportType, content) diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/ReviewWriteRateActivity.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/ReviewWriteRateActivity.kt index f98a26c9b..f0d9286e5 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/ReviewWriteRateActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/ReviewWriteRateActivity.kt @@ -20,6 +20,7 @@ import com.eatssu.android.presentation.UiEvent import com.eatssu.android.presentation.UiState import com.eatssu.android.presentation.base.BaseActivity import com.eatssu.android.presentation.util.showToast +import com.eatssu.common.EventLogger import dagger.hilt.android.AndroidEntryPoint import id.zelory.compressor.Compressor import kotlinx.coroutines.launch @@ -34,6 +35,7 @@ class ReviewWriteRateActivity : private var itemId: Long = 0 private lateinit var itemName: String + private var itemCount = 1L private var comment: String? = "" private var imageFile: File? = null @@ -47,6 +49,7 @@ class ReviewWriteRateActivity : Timber.d("고정메뉴 $itemName") itemId = intent.getLongExtra("itemId", -1) + itemCount = intent.getLongExtra("itemCount", 1) // 현재 메뉴명을 표시합니다. binding.menu.text = itemName @@ -133,6 +136,11 @@ class ReviewWriteRateActivity : ) viewModel.postReview(itemId, photoReview) + EventLogger.completeReviewV1( + rating = binding.rbMain.rating.toLong(), + selection = itemCount, + photoAttached = true + ) Timber.d("사진있는 리뷰 전송") } @@ -145,6 +153,11 @@ class ReviewWriteRateActivity : ) viewModel.postReview(itemId, review) + EventLogger.completeReviewV1( + rating = binding.rbMain.rating.toLong(), + selection = itemCount, + photoAttached = false + ) Timber.d("사진없는 리뷰 전송") } diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/ReviewWriteMenuActivity.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/ReviewWriteMenuActivity.kt index eb0511d1c..744461e19 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/ReviewWriteMenuActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/ReviewWriteMenuActivity.kt @@ -79,6 +79,7 @@ class ReviewWriteMenuActivity : val intent = Intent(this, ReviewWriteRateActivity::class.java) intent.putExtra("itemName", currentItem.first) intent.putExtra("itemId", currentItem.second) + intent.putExtra("itemCount", items.size.toLong()) // BActivity 실행 startActivity(intent) diff --git a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/VariableMenuPickAdapter.kt b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/VariableMenuPickAdapter.kt index 6dec55316..a57848dcd 100644 --- a/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/VariableMenuPickAdapter.kt +++ b/app/src/main/java/com/eatssu/android/presentation/cafeteria/review/write/menu/VariableMenuPickAdapter.kt @@ -6,7 +6,8 @@ import androidx.recyclerview.widget.RecyclerView import com.eatssu.android.databinding.ItemMenuPickBinding import com.eatssu.android.domain.model.MenuMini -class VariableMenuPickAdapter(private val menuList: List?) : +class +VariableMenuPickAdapter(private val menuList: List?) : RecyclerView.Adapter() { private val checkedItems: ArrayList> = ArrayList() diff --git a/app/src/main/java/com/eatssu/android/presentation/login/IntroActivity.kt b/app/src/main/java/com/eatssu/android/presentation/login/IntroActivity.kt index f04f0631c..75e9eff79 100644 --- a/app/src/main/java/com/eatssu/android/presentation/login/IntroActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/login/IntroActivity.kt @@ -6,11 +6,13 @@ import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import com.eatssu.android.databinding.ActivityIntroBinding +import com.eatssu.android.presentation.MainActivity import com.eatssu.android.presentation.UiEvent import com.eatssu.android.presentation.UiState -import com.eatssu.android.presentation.MainActivity import com.eatssu.android.presentation.util.showToast import com.eatssu.android.presentation.util.startActivity +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.LaunchPath import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -26,6 +28,7 @@ class IntroActivity : AppCompatActivity() { binding = ActivityIntroBinding.inflate(layoutInflater) enableEdgeToEdge() setContentView(binding.root) + log() lifecycleScope.launch { introViewModel.uiState.collectLatest { state -> @@ -55,4 +58,14 @@ class IntroActivity : AppCompatActivity() { } } } + + private fun log() { + val launchPath = intent.getStringExtra("launch_path") + when (launchPath) { + "widget" -> EventLogger.appLaunch(LaunchPath.WIDGET) + "notification" -> EventLogger.appLaunch(LaunchPath.LOCAL_NOTIFICATION) + // launch_path가 없으면 일반적인 앱 아이콘 클릭으로 간주 + else -> EventLogger.appLaunch(LaunchPath.ICON) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/map/MapFragmentView.kt b/app/src/main/java/com/eatssu/android/presentation/map/MapFragmentView.kt index a208bed7d..905954e1f 100644 --- a/app/src/main/java/com/eatssu/android/presentation/map/MapFragmentView.kt +++ b/app/src/main/java/com/eatssu/android/presentation/map/MapFragmentView.kt @@ -37,6 +37,7 @@ import com.eatssu.android.presentation.map.component.MapRestaurantBottomSheet import com.eatssu.android.presentation.map.component.PartnershipFilterToggle import com.eatssu.android.presentation.map.model.PlaceType import com.eatssu.android.presentation.mypage.userinfo.UserInfoActivity +import com.eatssu.common.EventLogger import com.eatssu.design_system.theme.Black import com.eatssu.design_system.theme.EatssuTheme import com.naver.maps.geometry.LatLng @@ -75,6 +76,9 @@ fun MapFragmentComposeView( val scope = rememberCoroutineScope() var selectedFilter by remember { mutableStateOf(FilterType.All) } + val departmentId = MySharedPreferences.getUserDepartmentId(context).toLong() + val collegeId = MySharedPreferences.getUserCollegeId(context).toLong() + val cameraPositionState = rememberCameraPositionState { position = CameraPosition( LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE), @@ -149,9 +153,14 @@ fun MapFragmentComposeView( // 제휴 정보 토글 event LaunchedEffect(selectedFilter) { when (selectedFilter) { - FilterType.All -> viewModel.loadPartnerships() + FilterType.All -> { + viewModel.loadPartnerships() + EventLogger.clickMap() + } FilterType.Mine -> { viewModel.loadUserCollegePartnerships() + + EventLogger.clickMapMine(collegeId, departmentId) } } } @@ -209,6 +218,12 @@ fun MapFragmentComposeView( // 특정 식당에 대한 제휴 정보 BottomSheet if (mapState.showPartnershipBottomSheet) { mapState.restaurantPartnershipInfo?.let { info -> + EventLogger.clickPartnerRestaurant( + college = collegeId, + major = departmentId, + partnerRestaurantId = info.id.toLong() + ) + MapRestaurantBottomSheet( storeName = info.storeName, placeType = when (info.restaurantType) { diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/MealInfoStateDefinition.kt b/app/src/main/java/com/eatssu/android/presentation/widget/MealInfoStateDefinition.kt index eb1a3d00b..25f1247b7 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/MealInfoStateDefinition.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/MealInfoStateDefinition.kt @@ -7,8 +7,8 @@ import androidx.datastore.core.DataStoreFactory import androidx.datastore.core.Serializer import androidx.datastore.dataStoreFile import androidx.glance.state.GlanceStateDefinition -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.model.WidgetMealInfo +import com.eatssu.common.enums.Restaurant import com.google.gson.Gson import com.google.gson.JsonObject import com.google.gson.JsonParser diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/MealWidgetReceiver.kt b/app/src/main/java/com/eatssu/android/presentation/widget/MealWidgetReceiver.kt index de8939a6e..492486a66 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/MealWidgetReceiver.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/MealWidgetReceiver.kt @@ -4,10 +4,13 @@ import android.content.Context import androidx.glance.appwidget.GlanceAppWidget import androidx.glance.appwidget.GlanceAppWidgetReceiver import com.eatssu.android.presentation.widget.ui.MealWidget +import com.eatssu.common.EventLogger +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.runBlocking import timber.log.Timber import java.io.File +@AndroidEntryPoint class MealWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget get() = MealWidget() @@ -31,6 +34,9 @@ class MealWidgetReceiver : GlanceAppWidgetReceiver() { dataStoreFile.delete() Timber.d("Deleted DataStore file for widget $appWidgetId") } + + EventLogger.removeWidget() + } } catch (e: Exception) { Timber.e("Failed to cleanup DataStore for widget $appWidgetId: ${e.message}") diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/WidgetCacheManager.kt b/app/src/main/java/com/eatssu/android/presentation/widget/WidgetCacheManager.kt index 9f0f60742..4d5732dc5 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/WidgetCacheManager.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/WidgetCacheManager.kt @@ -3,8 +3,8 @@ package com.eatssu.android.presentation.widget import android.os.Build import androidx.annotation.RequiresApi -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.model.WidgetMealInfo +import com.eatssu.common.enums.Restaurant import timber.log.Timber import java.time.LocalDateTime diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/WidgetMealList.kt b/app/src/main/java/com/eatssu/android/presentation/widget/WidgetMealList.kt index 8ae14206c..5a40cdbc4 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/WidgetMealList.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/WidgetMealList.kt @@ -1,6 +1,6 @@ package com.eatssu.android.presentation.widget -import com.eatssu.android.data.enums.Restaurant +import com.eatssu.common.enums.Restaurant // 각 식사별로 여러 메뉴 그룹을 지원하도록 구조 변경 // 예: lunch = ([ ["돈목살김치찜", "단호박카레볶음"], ["간짜장덮밥", "고추튀김"] ], "lunch") diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/ui/MealWidget.kt b/app/src/main/java/com/eatssu/android/presentation/widget/ui/MealWidget.kt index ef3c79cfa..d2fb68b11 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/ui/MealWidget.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/ui/MealWidget.kt @@ -42,7 +42,6 @@ import androidx.glance.text.FontWeight import androidx.glance.text.Text import androidx.glance.text.TextStyle import com.eatssu.android.R -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.model.WidgetMealInfo import com.eatssu.android.domain.usecase.widget.LoadRestaurantByFileKeyUseCase import com.eatssu.android.presentation.widget.MealInfoStateDefinition @@ -51,6 +50,7 @@ import com.eatssu.android.presentation.widget.theme.EATSSUWidgetColorScheme import com.eatssu.android.presentation.widget.util.MealTime import com.eatssu.android.presentation.widget.util.WidgetDataDisplayManager import com.eatssu.android.presentation.widget.util.launchApp +import com.eatssu.common.enums.Restaurant import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors @@ -119,13 +119,13 @@ class MealWidget : GlanceAppWidget() { MealWidgetContent( mealTime = mealTime, mealList = mealList, - restaurant = restaurant?.displayName ?: "", + restaurant = restaurant?.korean ?: "", glanceId = id, ) } else { MealWidgetError( mealTime = mealTime, - restaurant = restaurant?.displayName ?: "", + restaurant = restaurant?.korean ?: "", text = "오늘의 메뉴가 없습니다.", glanceId = id, ) @@ -135,7 +135,7 @@ class MealWidget : GlanceAppWidget() { is WidgetMealInfo.Loading -> { // Loading 상태일 때도 저장된 식당 정보 표시 MealWidgetError( - restaurant = restaurant?.displayName ?: "", + restaurant = restaurant?.korean ?: "", mealTime = "점심", text = "로딩 중", glanceId = id, @@ -144,7 +144,7 @@ class MealWidget : GlanceAppWidget() { is WidgetMealInfo.Unavailable -> { MealWidgetError( - restaurant = restaurant?.displayName ?: "", + restaurant = restaurant?.korean ?: "", mealTime = "점심", text = "네트워크 연결 상태를 확인해주세요.", glanceId = id, @@ -302,7 +302,7 @@ class MealWidget : GlanceAppWidget() { @Preview @Composable fun MealWidgetPreview() { - MealWidgetContent("저녁", listOf(listOf("밥", "국", "반찬", "음료")), Restaurant.DODAM.displayName) + MealWidgetContent("저녁", listOf(listOf("밥", "국", "반찬", "음료")), Restaurant.DODAM.korean) } @RequiresApi(Build.VERSION_CODES.O) @@ -310,6 +310,6 @@ class MealWidget : GlanceAppWidget() { @Preview @Composable fun MealWidgetPreviewError() { - MealWidgetError("저녁", Restaurant.DODAM.displayName, "에러임") + MealWidgetError("저녁", Restaurant.DODAM.korean, "에러임") } } diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingActivity.kt b/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingActivity.kt index bff0fd799..fb9db2f79 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingActivity.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingActivity.kt @@ -17,9 +17,9 @@ import androidx.compose.ui.platform.LocalContext import androidx.glance.GlanceId import androidx.glance.appwidget.GlanceAppWidgetManager import androidx.lifecycle.lifecycleScope -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.usecase.widget.SaveRestaurantByFileKeyUseCase import com.eatssu.android.presentation.widget.MealWorker +import com.eatssu.common.enums.Restaurant import com.eatssu.design_system.theme.EatssuTheme import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -39,7 +39,7 @@ class WidgetSettingActivity : ComponentActivity() { EatssuTheme { val restaurantOptions = Restaurant.getVariableRestaurantList().map { - it.displayName + it.korean } // 변동 식당만 불러옵니다. 하드코딩 x var selectedRestaurant by rememberSaveable { mutableStateOf(restaurantOptions[0]) } diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingScreen.kt b/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingScreen.kt index 040d50705..8908c5e93 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingScreen.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/ui/WidgetSettingScreen.kt @@ -14,7 +14,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.eatssu.android.data.enums.Restaurant.Companion.fromDisplayName +import com.eatssu.common.EventLogger +import com.eatssu.common.enums.Restaurant +import com.eatssu.common.enums.Restaurant.Companion.fromKorean import com.eatssu.design_system.component.EatSsuButton import com.eatssu.design_system.component.EatSsuRadioButtonGroup import com.eatssu.design_system.component.EatSsuTopBar @@ -26,7 +28,7 @@ fun WidgetSettingScreen( restaurantOptionList: List, selectedRestaurant: String, onSelectRestaurant: (String) -> Unit, - onConfirm: (String) -> Unit = {}, + onConfirm: (Restaurant) -> Unit = {}, onBack: () -> Unit = {} // 뒤로가기 동작을 위한 람다 추가 ) { Scaffold( @@ -63,8 +65,9 @@ fun WidgetSettingScreen( text = "선택하기", onClick = { onConfirm( - fromDisplayName(selectedRestaurant) + fromKorean(selectedRestaurant) ) + EventLogger.addWidget(Restaurant.fromKorean(selectedRestaurant)) } ) } diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/util/WidgetDataDisplayManager.kt b/app/src/main/java/com/eatssu/android/presentation/widget/util/WidgetDataDisplayManager.kt index 9d3060592..4efe91b04 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/util/WidgetDataDisplayManager.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/util/WidgetDataDisplayManager.kt @@ -2,12 +2,12 @@ package com.eatssu.android.presentation.widget.util import android.os.Build import androidx.annotation.RequiresApi -import com.eatssu.android.data.enums.Restaurant import com.eatssu.android.domain.model.WidgetMealInfo import com.eatssu.android.domain.usecase.widget.GetTodayMealUseCase import com.eatssu.android.domain.usecase.widget.MealState import com.eatssu.android.presentation.util.CalendarUtil import com.eatssu.android.presentation.widget.WidgetCacheManager +import com.eatssu.common.enums.Restaurant import timber.log.Timber import java.time.LocalTime diff --git a/app/src/main/java/com/eatssu/android/presentation/widget/util/launchApp.kt b/app/src/main/java/com/eatssu/android/presentation/widget/util/launchApp.kt index 1d4fe2e37..1b19b4b38 100644 --- a/app/src/main/java/com/eatssu/android/presentation/widget/util/launchApp.kt +++ b/app/src/main/java/com/eatssu/android/presentation/widget/util/launchApp.kt @@ -8,6 +8,8 @@ fun Context.launchApp() { val deepLinkUri = Uri.parse("eatssu://root") val intent = Intent(Intent.ACTION_VIEW, deepLinkUri) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // 위젯에서 온 것을 표시하는 플래그 추가 + intent.putExtra("launch_path", "widget") runCatching { this.startActivity(intent) } } \ No newline at end of file diff --git a/core/common/.gitignore b/core/common/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/core/common/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts new file mode 100644 index 000000000..645e1e40f --- /dev/null +++ b/core/common/build.gradle.kts @@ -0,0 +1,48 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.google.services) +} + +android { + namespace = "com.eatssu.common" + compileSdk = 35 + + defaultConfig { + minSdk = 23 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.espresso.core) + + // Firebase + implementation(platform(libs.firebase.bom)) + implementation(libs.firebase.analytics) +} \ No newline at end of file diff --git a/core/common/consumer-rules.pro b/core/common/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb diff --git a/core/common/proguard-rules.pro b/core/common/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/core/common/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/core/common/src/androidTest/java/com/eatssu/common/ExampleInstrumentedTest.kt b/core/common/src/androidTest/java/com/eatssu/common/ExampleInstrumentedTest.kt new file mode 100644 index 000000000..1b52bd0e4 --- /dev/null +++ b/core/common/src/androidTest/java/com/eatssu/common/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.eatssu.common + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.eatssu.common.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/core/common/src/main/java/com/eatssu/common/EventLogger.kt b/core/common/src/main/java/com/eatssu/common/EventLogger.kt new file mode 100644 index 000000000..12ccf3ea6 --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/EventLogger.kt @@ -0,0 +1,141 @@ +package com.eatssu.common + +import com.eatssu.common.enums.LaunchPath +import com.eatssu.common.enums.Restaurant +import com.eatssu.common.enums.Time +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.analytics.ktx.analytics +import com.google.firebase.analytics.logEvent +import com.google.firebase.ktx.Firebase + +private val firebaseAnalytics: FirebaseAnalytics by lazy { Firebase.analytics } + +object EventLogger { + + fun setUserProperties(vararg properties: Pair) { + properties.forEach { property -> + firebaseAnalytics.setUserProperty(property.first, property.second) + } + } + + fun appLaunch(launchPath: LaunchPath) { + firebaseAnalytics.logEvent("app_launch") { + param("launch_path", launchPath.value) + } + } + + fun clickRestaurantInfo(restaurant: Restaurant) { + firebaseAnalytics.logEvent("click_restaurant_info") { + param("restaurants", restaurant.value) + } + } + + fun selectMealTime(time: Time) { + firebaseAnalytics.logEvent("select_mealtime") { + param("mealtime", time.value) + } + } + + fun selectDay(day: String) { + val weekDay = when (day) { + "SUNDAY" -> "sun" + "MONDAY" -> "mon" + "TUESDAY" -> "tue" + "WEDNESDAY" -> "wed" + "THURSDAY" -> "thu" + "FRIDAY" -> "fri" + "SATURDAY" -> "sat" + else -> { + "" + } + } + firebaseAnalytics.logEvent("click_day") { + param("day", weekDay) + } + } + + fun clickMenu(restaurant: Restaurant) { + firebaseAnalytics.logEvent("click_menu") { + param("restaurants", restaurant.value) + } + } + + fun writeReview() { //todo v2로 바꿀시 v1 제거 + firebaseAnalytics.logEvent("write_review_v1", null) + } + + fun completeReviewV1( + rating: Long, + selection: Long, + photoAttached: Boolean, + ) { + firebaseAnalytics.logEvent("complete_review_v1") { + param("rating", rating) + param("selection", selection) + param("photo_attached", if (photoAttached) 1 else 0) + } + } + + fun completeReviewV2( + rating: Long, + likes: Long, + photoAttached: Boolean, + ) { + firebaseAnalytics.logEvent("complete_review_v2") { + param("rating", rating) + param("likes", likes) + param("photo_attached", if (photoAttached) 1 else 0) + } + } + + + fun clickMap() { + firebaseAnalytics.logEvent("click_map", null) + } + + fun clickMapMine( + college: Long, + major: Long, + ) { + firebaseAnalytics.logEvent("click_map_mine") { + param("college", college) + param("major", major) + } + } + + fun clickPartnerRestaurant( + college: Long, + major: Long, + partnerRestaurantId: Long + ) { + firebaseAnalytics.logEvent("click_partner_restaurant") { + param("college", college) + param("major", major) + param("partner_restaurant_id", partnerRestaurantId) + } + } + + fun addWidget(restaurant: Restaurant) { + firebaseAnalytics.logEvent("add_widget") { + param("restaurants", restaurant.value) + } + } + + fun removeWidget() { + firebaseAnalytics.logEvent("remove_widget", null) + } + + //todo 파라미터 넣을지 추후 논의 + fun removeWidget(restaurant: Restaurant) { + firebaseAnalytics.logEvent("remove_widget") { + param("restaurants", restaurant.value) + } + } + + //todo change_widget + fun changeWidget(restaurant: Restaurant) { + firebaseAnalytics.logEvent("change_widget") { + param("restaurants", restaurant.value) + } + } +} \ No newline at end of file diff --git a/core/common/src/main/java/com/eatssu/common/enums/LaunchPath.kt b/core/common/src/main/java/com/eatssu/common/enums/LaunchPath.kt new file mode 100644 index 000000000..fdde27cc0 --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/enums/LaunchPath.kt @@ -0,0 +1,7 @@ +package com.eatssu.common.enums + +enum class LaunchPath(val value: String) { + ICON("icon"), + LOCAL_NOTIFICATION("local_notification"), + WIDGET("widget"), +} \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/enums/MenuType.kt b/core/common/src/main/java/com/eatssu/common/enums/MenuType.kt similarity index 73% rename from app/src/main/java/com/eatssu/android/data/enums/MenuType.kt rename to core/common/src/main/java/com/eatssu/common/enums/MenuType.kt index 209021eb5..2606204fa 100644 --- a/app/src/main/java/com/eatssu/android/data/enums/MenuType.kt +++ b/core/common/src/main/java/com/eatssu/common/enums/MenuType.kt @@ -1,4 +1,4 @@ -package com.eatssu.android.data.enums +package com.eatssu.common.enums enum class MenuType (val displayName: String){ FIXED("고정메뉴"), diff --git a/core/common/src/main/java/com/eatssu/common/enums/Provider.kt b/core/common/src/main/java/com/eatssu/common/enums/Provider.kt new file mode 100644 index 000000000..002b212fb --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/enums/Provider.kt @@ -0,0 +1,5 @@ +package com.eatssu.common.enums + +enum class Provider { + KAKAO +} \ No newline at end of file diff --git a/core/common/src/main/java/com/eatssu/common/enums/ReportType.kt b/core/common/src/main/java/com/eatssu/common/enums/ReportType.kt new file mode 100644 index 000000000..f5580f6fa --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/enums/ReportType.kt @@ -0,0 +1,11 @@ +package com.eatssu.common.enums + + +enum class ReportType(val description: String) { + NO_ASSOCIATE_CONTENT("메뉴와 관련없는 내용"), + IMPROPER_CONTENT("음란성, 욕설 등 부적절한 내용"), + IMPROPER_ADVERTISEMENT("부적절한 홍보 또는 광고"), + COPY("리뷰 작성 취지에 맞지 않은 내용 (복사글 등)"), + COPYRIGHT("저작권 도용 의심 (사진 등)"), + EXTRA("기타 (하단 내용 작성)") +} \ No newline at end of file diff --git a/core/common/src/main/java/com/eatssu/common/enums/Restaurant.kt b/core/common/src/main/java/com/eatssu/common/enums/Restaurant.kt new file mode 100644 index 000000000..0cbe90e64 --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/enums/Restaurant.kt @@ -0,0 +1,26 @@ +package com.eatssu.common.enums + + +enum class Restaurant(val value: String, val korean: String, val menuType: MenuType) { + HAKSIK("haksik", "학생 식당", MenuType.VARIABLE), + DODAM("dodam", "도담 식당", MenuType.VARIABLE), + DORMITORY("dormitory", "기숙사 식당", MenuType.VARIABLE), + FACULTY("faculty", "FACULTY (교직원 전용)", MenuType.VARIABLE), + FOOD_COURT("food_court", "푸드 코트", MenuType.FIXED), + SNACK_CORNER("snack_corner", "스낵 코너", MenuType.FIXED), + THE_KITCHEN("the_kitchen", "더 키친", MenuType.FIXED); + + companion object { + + fun getVariableRestaurantList(): List { + return entries.filter { it.menuType == MenuType.VARIABLE } + } + + fun fromRestaurantEnumName(enumName: String): String { + return entries.find { it.name == enumName }?.korean ?: "" + } + + fun fromKorean(name: String): Restaurant = + entries.find { it.korean == name } ?: error("Unknown display name: $name") + } +} \ No newline at end of file diff --git a/core/common/src/main/java/com/eatssu/common/enums/Time.kt b/core/common/src/main/java/com/eatssu/common/enums/Time.kt new file mode 100644 index 000000000..e894f254c --- /dev/null +++ b/core/common/src/main/java/com/eatssu/common/enums/Time.kt @@ -0,0 +1,13 @@ +package com.eatssu.common.enums + +enum class Time(val value: String, val korean: String) { + MORNING("breakfast", "조식"), + LUNCH("lunch", "중식"), + DINNER("dinner", "석식"); + + companion object { + fun fromTimeEnumName(enumName: String): String { + return entries.find { it.name == enumName }?.korean ?: "" + } + } +} \ No newline at end of file diff --git a/core/common/src/test/java/com/eatssu/common/ExampleUnitTest.kt b/core/common/src/test/java/com/eatssu/common/ExampleUnitTest.kt new file mode 100644 index 000000000..9345dcd95 --- /dev/null +++ b/core/common/src/test/java/com/eatssu/common/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.eatssu.common + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bc75deb5b..fa573daea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,7 @@ activityCompose = "1.9.2" android = "8.6.1" androidx-core = "1.7.0" androidx-appcompat = "1.6.1" +hiltAndroidCompiler = "2.42" lifecycleRuntimeCompose = "2.8.7" animation = "1.7.8" composeBomVersion = "2025.03.00" diff --git a/settings.gradle b/settings.gradle index 2691ac0e2..5c82c91af 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,3 +18,4 @@ dependencyResolutionManagement { rootProject.name = "EatSSU-Android" include ':app' include ':core:design-system' +include ':core:common'