Skip to content

Commit

Permalink
Merge pull request #87 from everymeals/feature/univ_save
Browse files Browse the repository at this point in the history
[feature/univ_save] 대학 정보 저장 및 불러오기 구현
  • Loading branch information
kez-lab authored Nov 20, 2023
2 parents b38640b + 1dc2526 commit 45d8094
Show file tree
Hide file tree
Showing 27 changed files with 298 additions and 23 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,7 @@ dependencies {
// Serialization
implementation(libs.serialization)
implementation(libs.kotlin.serilization)

//DataStore
implementation(libs.data.store)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.everymeal.everymeal_android.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DataBaseModule {

private const val DATASTORE_NAME = "everymeal_datastore"

@Singleton
@Provides
fun providePreferencesDataStore(@ApplicationContext context: Context): DataStore<Preferences> =
PreferenceDataStoreFactory.create(
produceFile = { context.preferencesDataStoreFile(DATASTORE_NAME) }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ object NetworkModule {
fun provideAuthApi(retrofit: Retrofit): AuthApi {
return retrofit.create(AuthApi::class.java)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package com.everymeal.everymeal_android.di

import com.everymeal.data.datasource.auth.AuthRemoteDataSource
import com.everymeal.data.datasource.auth.AuthRemoteRemoteDataSourceImpl
import com.everymeal.data.datasource.local.LocalDataSource
import com.everymeal.data.datasource.local.LocalDataSourceImpl
import com.everymeal.data.datasource.onboarding.OnboardingDataSource
import com.everymeal.data.datasource.onboarding.OnboardingDataSourceImpl
import com.everymeal.data.repository.local.LocalRepositoryImpl
import com.everymeal.data.repository.DefaultAuthRepository
import com.everymeal.data.repository.onboarding.OnboardingRepositoryImpl
import com.everymeal.domain.repository.local.LocalRepository
import com.everymeal.domain.repository.auth.AuthRepository
import com.everymeal.domain.repository.onboarding.OnboardingRepository
import dagger.Binds
Expand All @@ -30,6 +34,18 @@ abstract class RepositoryModule {
onboardingDataSourceImpl: OnboardingDataSourceImpl
): OnboardingDataSource

@Singleton
@Binds
abstract fun bindLocalRepository(
localRepositoryImpl: LocalRepositoryImpl
): LocalRepository

@Singleton
@Binds
abstract fun bindLocalDataSource(
localDataSourceImpl: LocalDataSourceImpl
): LocalDataSource

@Singleton
@Binds
abstract fun bindAuthRemoteDataSource(
Expand Down
3 changes: 3 additions & 0 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ dependencies {
// Serialization
implementation(libs.serialization)
implementation(libs.kotlin.serilization)

//DataStore
implementation(libs.data.store)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.everymeal.data.datasource.local

import kotlinx.coroutines.flow.Flow

interface LocalDataSource {
suspend fun saveUniversity(index : Int, univName : String)

suspend fun getUniversityIndex() : Flow<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.everymeal.data.datasource.local

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import java.io.IOException
import javax.inject.Inject

object DataStoreKey {
val UNIVERSITY_INDEX = stringPreferencesKey("univ_index")
val UNIVERSITY_NAME = stringPreferencesKey("univ_name")
}

class LocalDataSourceImpl @Inject constructor(
private val dataStore: DataStore<Preferences>
) : LocalDataSource {
override suspend fun saveUniversity(index: Int, univName: String) {
dataStore.edit {
it[DataStoreKey.UNIVERSITY_INDEX] = index.toString()
it[DataStoreKey.UNIVERSITY_NAME] = univName
}
}

override suspend fun getUniversityIndex(): Flow<String> {
return dataStore.data
.catch { exception ->
if (exception is IOException) {
exception.printStackTrace()
emit(emptyPreferences())
} else {
throw exception
}
}
.map { prefs ->
prefs[DataStoreKey.UNIVERSITY_INDEX].orEmpty()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.everymeal.data.datasource.onboarding

import com.everymeal.data.model.onboarding.UniversityData
import com.everymeal.data.model.onboarding.UniversityResponse

interface OnboardingDataSource {
suspend fun getUniversity(): Result<List<UniversityData>>
suspend fun getUniversity(): Result<List<UniversityResponse>>
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.everymeal.data.datasource.onboarding

import com.everymeal.data.model.onboarding.UniversityData
import com.everymeal.data.model.onboarding.UniversityResponse
import com.everymeal.data.model.unwrapData
import com.everymeal.data.service.onboarding.OnboardingApi
import javax.inject.Inject
Expand All @@ -9,7 +9,7 @@ class OnboardingDataSourceImpl @Inject constructor(
private val onboardingApi: OnboardingApi
) : OnboardingDataSource {

override suspend fun getUniversity(): Result<List<UniversityData>> {
override suspend fun getUniversity(): Result<List<UniversityResponse>> {
return runCatching { onboardingApi.getUniversity() }.unwrapData()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import com.everymeal.domain.model.onboarding.GetUniversityEntity
import kotlinx.serialization.Serializable

@Serializable
data class UniversityData(
data class UniversityResponse(
val idx: Int,
val universityName: String,
val campusName: String,
val universityShortName: String
)

fun List<UniversityData>.toUniversityEntity(): GetUniversityEntity {
fun List<UniversityResponse>.toUniversityEntity(): GetUniversityEntity {
val universityDataList = this.map { result ->
GetUniversityEntity.UniversityData(
idx = result.idx,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.everymeal.data.repository.local

import com.everymeal.data.datasource.local.LocalDataSource
import com.everymeal.domain.repository.local.LocalRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class LocalRepositoryImpl @Inject constructor(
private val localDataSource: LocalDataSource
) : LocalRepository {

override suspend fun saveUniversity(index: Int, univName: String) {
localDataSource.saveUniversity(index, univName)
}

override suspend fun getUniversityIndex(): Flow<String> {
return localDataSource.getUniversityIndex()
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.everymeal.data.service.onboarding

import com.everymeal.data.model.BaseResponse
import com.everymeal.data.model.onboarding.UniversityData
import com.everymeal.data.model.onboarding.UniversityResponse
import retrofit2.http.GET

interface OnboardingApi {

@GET("/api/v1/universities")
suspend fun getUniversity(): BaseResponse<List<UniversityData>>
suspend fun getUniversity(): BaseResponse<List<UniversityResponse>>
}
3 changes: 3 additions & 0 deletions domain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ java {
dependencies {
// Hilt
implementation(libs.hilt.core)

// Coroutines
implementation(libs.kotlin.coroutines)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.everymeal.domain.repository.local

import kotlinx.coroutines.flow.Flow

interface LocalRepository {
suspend fun saveUniversity(index : Int, univName : String)

suspend fun getUniversityIndex() : Flow<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.everymeal.domain.usecase.local

import com.everymeal.domain.repository.local.LocalRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetUniversityIndexUseCase @Inject constructor(
private val localRepository: LocalRepository
) {
suspend operator fun invoke() : Flow<String> {
return localRepository.getUniversityIndex()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.everymeal.domain.usecase.local

import com.everymeal.domain.repository.local.LocalRepository
import com.everymeal.domain.repository.onboarding.OnboardingRepository
import javax.inject.Inject

class SaveUniversityUseCase @Inject constructor(
private val localRepository: LocalRepository
) {
suspend operator fun invoke(
index : Int,
univName : String
) {
localRepository.saveUniversity(index, univName)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.everymeal.domain.usecase.onboarding

import com.everymeal.domain.model.onboarding.GetUniversityEntity
import com.everymeal.domain.repository.onboarding.OnboardingRepository
import javax.inject.Inject

class GetUniversityUseCase @Inject constructor(
private val onboardingRepository: OnboardingRepository
) {
suspend operator fun invoke() = onboardingRepository.getUniversity()
suspend operator fun invoke() :Result<GetUniversityEntity> {
return onboardingRepository.getUniversity()
}
}
8 changes: 8 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ lottie = "6.1.0"
compose-navigation = "2.7.4"
accompanist = "0.33.0-alpha"

data-store = "1.0.0"
kotlin-coroutines = "1.7.3"

[libraries]
agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil-compose" }
Expand Down Expand Up @@ -69,6 +72,11 @@ compose-lottie = { module = "com.airbnb.android:lottie-compose", version.ref = "
#Compose-Navigation
compose-navigation = { module = "androidx.navigation:navigation-compose", version.ref = "compose-navigation" }

#data-store
data-store = { module = "androidx.datastore:datastore-preferences", version.ref = "data-store" }

#kotlin-coroutines
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fun OnboardingScreen(
}
Spacer(modifier = Modifier.size(30.dp))
EveryMealMainButton(
text = stringResource(id = R.string.next),
text = stringResource(id = R.string.start),
onClick = onNavigateToUnivSelect
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ class UnivSelectContract {
val univSelectLoadState: LoadState = LoadState.LOADING,
val selectedUniv: String = "",
val universities: List<UniversityData> = emptyList(),
val networkErrorDialog: Boolean = true
val networkErrorDialog: Boolean = true,
val univIdx: Int = 0,
val univSelectFullName: String = "",
val campusName: String = ""
) : ViewState

/*
Expand All @@ -25,9 +28,16 @@ class UnivSelectContract {
*/
sealed class UnivSelectEvent : ViewEvent {
object InitUnivSelectScreen : UnivSelectEvent()
object SelectButtonClicked : UnivSelectEvent()
data class SelectButtonClicked(
val univIdx: Int,
val univSelectFullName: String,
val campusName: String
) : UnivSelectEvent()
data class SelectedUniv(
val selectedUniv: String
val selectedUniv: String,
val univIdx: Int,
val univSelectFullName: String,
val campusName: String
) : UnivSelectEvent()
data class NetworkErrorDialogClicked(
val dialogStateChange: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ fun UnivSelectScreen(
index = index
) {
viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectedUniv(
"${item.universityShortName}+${item.campusName}")
selectedUniv = "${item.universityShortName}+${item.campusName}",
univIdx = item.idx,
univSelectFullName = item.universityName,
campusName = item.campusName)
)
}
}
Expand Down Expand Up @@ -161,7 +164,11 @@ fun UnivSelectScreen(
text = stringResource(R.string.select),
enabled = viewState.selectedUniv.isNotEmpty(),
) {
viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectButtonClicked)
viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectButtonClicked(
univIdx = viewState.univIdx,
univSelectFullName = viewState.univSelectFullName,
campusName = viewState.campusName
))
}
}
}
Expand Down
Loading

0 comments on commit 45d8094

Please sign in to comment.