Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.eatssu.android.data.repository

import com.eatssu.android.R
import com.eatssu.android.domain.model.RestaurantInfo
import com.eatssu.android.domain.repository.FirebaseRemoteConfigRepository
import com.eatssu.common.enums.Restaurant
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.tasks.await
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FirebaseRemoteConfigRepositoryImpl @Inject constructor(
) : FirebaseRemoteConfigRepository {

private val instance = FirebaseRemoteConfig.getInstance()

init {
// Remote Config 설정 초기화 (fetchAndActivate는 각 값 가져오기 전에 호출)
val configSettings = FirebaseRemoteConfigSettings.Builder()
.setMinimumFetchIntervalInSeconds(600)
.build()
instance.setConfigSettingsAsync(configSettings)
instance.setDefaultsAsync(R.xml.firebase_remote_config)
}

override suspend fun getMinimumVersionCode(): Long {
// 값을 가져오기 전에 fetchAndActivate 호출
// min fetch interval이 지나지 않았으면 로컬 캐시를 사용하고, 지났으면 서버에서 가져옵니다.
try {
instance.fetchAndActivate().await()
} catch (e: Exception) {
Timber.e(e, "RemoteConfig fetchAndActivate 실패")
}
return instance.getLong("android_version_code")
}

override suspend fun getRestaurantInfo(restaurant: Restaurant): RestaurantInfo? {
// 값을 가져오기 전에 fetchAndActivate 호출
// min fetch interval이 지나지 않았으면 로컬 캐시를 사용하고, 지났으면 서버에서 가져옵니다.
try {
instance.fetchAndActivate().await()
} catch (e: Exception) {
Timber.e(e, "RemoteConfig fetchAndActivate 실패")
}
return getCafeteriaInfo().find { it.enum == restaurant }
}

private fun getCafeteriaInfo(): List<RestaurantInfo> {
val json = instance.getString("cafeteria_information")
return runCatching { parseCafeteriaJson(json) }
.onFailure { Timber.e(it, "cafeteria_information JSON 파싱 실패") }
.getOrDefault(emptyList())
}

private fun parseCafeteriaJson(json: String): List<RestaurantInfo> {
return try {
val gson = Gson()
val listType = object : TypeToken<List<RestaurantInfo>>() {}.type
val dtoList: List<RestaurantInfo> = gson.fromJson(json, listType)

dtoList.map { dto ->
RestaurantInfo(
enum = dto.enum,
name = dto.name,
location = dto.location,
image = dto.image,
time = dto.time,
etc = dto.etc
).also {
Timber.d("Loaded cafeteria info: $it")
}
}
} catch (e: Exception) {
Timber.e(e, "Failed to parse cafeteria JSON")
emptyList()
}
}
}
6 changes: 0 additions & 6 deletions app/src/main/java/com/eatssu/android/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.eatssu.android.di

import android.app.Application
import android.content.Context
import com.eatssu.android.data.repository.FirebaseRemoteConfigRepository
import com.eatssu.android.data.repository.PreferencesRepository
import com.eatssu.android.data.repository.WidgetPreferencesRepository
import dagger.Module
Expand All @@ -28,11 +27,6 @@ object AppModule {
return PreferencesRepository(context)
}

@Provides
@Singleton
fun provideFirebaseRemoteConfigRepository(): FirebaseRemoteConfigRepository {
return FirebaseRemoteConfigRepository()
}

@Provides
@Singleton
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/eatssu/android/di/DataModule.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.eatssu.android.di


import com.eatssu.android.data.repository.FirebaseRemoteConfigRepositoryImpl
import com.eatssu.android.data.repository.HealthCheckRepositoryImpl
import com.eatssu.android.data.repository.MealRepositoryImpl
import com.eatssu.android.data.repository.MenuRepositoryImpl
import com.eatssu.android.data.repository.OauthRepositoryImpl
import com.eatssu.android.data.repository.PartnershipRepositoryImpl
import com.eatssu.android.data.repository.ReportRepositoryImpl
import com.eatssu.android.data.repository.UserRepositoryImpl
import com.eatssu.android.domain.repository.FirebaseRemoteConfigRepository
import com.eatssu.android.domain.repository.HealthCheckRepository
import com.eatssu.android.domain.repository.MealRepository
import com.eatssu.android.domain.repository.MenuRepository
Expand Down Expand Up @@ -66,4 +68,8 @@ abstract class DataModule {
menuRepositoryImpl: MenuRepositoryImpl,
): MenuRepository

@Binds
internal abstract fun bindsFirebaseRemoteConfigRepository(
firebaseRemoteConfigRepositoryImpl: FirebaseRemoteConfigRepositoryImpl,
): FirebaseRemoteConfigRepository
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ data class RestaurantInfo(
val enum: Restaurant,
val name: String,
val location: String,
val photoUrl: String,
val image: String,
val time: String,
val etc: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.eatssu.android.domain.repository

import com.eatssu.android.domain.model.RestaurantInfo
import com.eatssu.common.enums.Restaurant

interface FirebaseRemoteConfigRepository {

/**
* 앱의 최신 버전 코드 반환
* 값을 가져오기 전에 fetchAndActivate를 호출하여 최신 값을 가져옵니다.
*/
suspend fun getMinimumVersionCode(): Long

/**
* 특정 식당 정보를 Remote Config에서 가져옴
* 값을 가져오기 전에 fetchAndActivate를 호출하여 최신 값을 가져옵니다.
*/
suspend fun getRestaurantInfo(restaurant: Restaurant): RestaurantInfo?
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.eatssu.android.R
import com.eatssu.android.data.repository.FirebaseRemoteConfigRepository
import com.eatssu.android.presentation.common.ForceUpdateDialogActivity
import com.eatssu.android.presentation.common.NetworkConnection
import com.eatssu.android.presentation.common.VersionViewModel
import com.eatssu.android.presentation.common.VersionViewModelFactory
import com.eatssu.android.presentation.login.LoginActivity
import com.eatssu.android.presentation.util.observeNetworkError
import com.eatssu.common.EventLogger
Expand All @@ -45,8 +40,6 @@ abstract class BaseActivity<B : ViewBinding>(
protected lateinit var toolbarTitle: TextView
private lateinit var backBtn: MaterialCardView

private lateinit var versionViewModel: VersionViewModel
private lateinit var firebaseRemoteConfigRepository: FirebaseRemoteConfigRepository

private val networkCheck: NetworkConnection by lazy {
NetworkConnection(this)
Expand All @@ -72,16 +65,6 @@ abstract class BaseActivity<B : ViewBinding>(

networkCheck.register() // 네트워크 객체 등록

firebaseRemoteConfigRepository = FirebaseRemoteConfigRepository()
versionViewModel = ViewModelProvider(
this,
VersionViewModelFactory(firebaseRemoteConfigRepository)
)[VersionViewModel::class.java]

if (versionViewModel.checkForceUpdate()) {
showForceUpdateDialog()
}

_binding = bindingFactory(layoutInflater, findViewById(R.id.fl_content), true)

// refreshtoken 관리
Expand Down Expand Up @@ -123,20 +106,16 @@ abstract class BaseActivity<B : ViewBinding>(
private fun observeTokenExpiration() {
lifecycleScope.launch {
TokenEventBus.tokenExpired.collect {
Toast.makeText(
this@BaseActivity,
getString(R.string.token_expired), Toast.LENGTH_SHORT
).show()
Toast.makeText(this@BaseActivity,
getString(R.string.token_expired), Toast.LENGTH_SHORT).show()
navigateToLogin()
}
}

lifecycleScope.launch {
TokenEventBus.tokenServerError.collect {
Toast.makeText(
this@BaseActivity,
getString(R.string.token_server_error), Toast.LENGTH_SHORT
)
Toast.makeText(this@BaseActivity,
getString(R.string.token_server_error), Toast.LENGTH_SHORT)
.show()
navigateToLogin()
}
Expand Down Expand Up @@ -178,10 +157,6 @@ abstract class BaseActivity<B : ViewBinding>(
return super.dispatchTouchEvent(ev)
}

private fun showForceUpdateDialog() {
val intent = Intent(this, ForceUpdateDialogActivity::class.java)
startActivity(intent)
}

override fun onResume() {
super.onResume()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,16 @@ class InfoBottomSheetFragment : BottomSheetDialogFragment() {
binding.tvName.text = restaurantType.korean

CoroutineScope(Dispatchers.Main).launch {
infoViewModel.infoList.collect {
val restaurantInfo = infoViewModel.getRestaurantInfo(restaurantType)
val restaurantInfo = infoViewModel.getRestaurantInfo(restaurantType)

restaurantInfo?.let {
binding.tvLocation.text = it.location
binding.tvTime.text = it.time
binding.tvEtc.text = it.etc
restaurantInfo?.let {
binding.tvLocation.text = it.location
binding.tvTime.text = it.time
binding.tvEtc.text = it.etc

Glide.with(this@InfoBottomSheetFragment)
.load(it.photoUrl)
.into(binding.ivCafeteriaPhoto)
}
Glide.with(this@InfoBottomSheetFragment)
.load(it.image)
.into(binding.ivCafeteriaPhoto)
}
}
}
Expand Down
Loading