Skip to content

Commit

Permalink
Merge pull request #86 from everymeals/feature/school_auth_screen
Browse files Browse the repository at this point in the history
[Feature/school_auth_screen]: 학교 이메일 인증 작업
kez-lab authored Nov 15, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 1bc3d35 + e72050b commit b38640b
Showing 21 changed files with 581 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.everymeal.everymeal_android.di

import com.everymeal.data.service.auth.AuthApi
import com.everymeal.data.service.onboarding.OnboardingApi
import com.everymeal.everymeal_android.BuildConfig
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
@@ -24,7 +25,7 @@ object NetworkModule {

@Provides
@Singleton
fun provideClient(): OkHttpClient {
fun provideClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)
.readTimeout(100, TimeUnit.SECONDS)
@@ -46,4 +47,10 @@ object NetworkModule {
fun provideOnboardingApi(retrofit: Retrofit): OnboardingApi {
return retrofit.create(OnboardingApi::class.java)
}
}

@Provides
@Singleton
fun provideAuthApi(retrofit: Retrofit): AuthApi {
return retrofit.create(AuthApi::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
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.onboarding.OnboardingDataSource
import com.everymeal.data.datasource.onboarding.OnboardingDataSourceImpl
import com.everymeal.data.repository.DefaultAuthRepository
import com.everymeal.data.repository.onboarding.OnboardingRepositoryImpl
import com.everymeal.domain.repository.auth.AuthRepository
import com.everymeal.domain.repository.onboarding.OnboardingRepository
import dagger.Binds
import dagger.Module
@@ -25,4 +29,16 @@ abstract class RepositoryModule {
abstract fun bindOnboardingDataSource(
onboardingDataSourceImpl: OnboardingDataSourceImpl
): OnboardingDataSource
}

@Singleton
@Binds
abstract fun bindAuthRemoteDataSource(
authRemoteDataSourceImpl: AuthRemoteRemoteDataSourceImpl
): AuthRemoteDataSource

@Singleton
@Binds
abstract fun bindAuthRepository(
defaultAuthRepository: DefaultAuthRepository
): AuthRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.everymeal.data.datasource.auth

import com.everymeal.domain.model.auth.Email

interface AuthRemoteDataSource {
suspend fun postEmail(email: Email): Result<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.everymeal.data.datasource.auth

import com.everymeal.data.model.auth.toEmailRequest
import com.everymeal.data.model.unwrapData
import com.everymeal.data.service.auth.AuthApi
import com.everymeal.domain.model.auth.Email
import javax.inject.Inject

class AuthRemoteRemoteDataSourceImpl @Inject constructor(
private val authApi: AuthApi
) : AuthRemoteDataSource {

override suspend fun postEmail(email: Email): Result<String> = runCatching {
authApi.postEmail(email.toEmailRequest())
}.unwrapData()
}
20 changes: 20 additions & 0 deletions data/src/main/java/com/everymeal/data/model/auth/EmailRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.everymeal.data.model.auth


import com.everymeal.domain.model.auth.Email
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class EmailRequest(
@SerialName("email")
val email: String? = null
)

fun EmailRequest.toEmail() = Email(
email = email ?: ""
)

fun Email.toEmailRequest() = EmailRequest(
email = email
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.everymeal.data.repository

import com.everymeal.data.datasource.auth.AuthRemoteDataSource
import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.repository.auth.AuthRepository
import javax.inject.Inject

class DefaultAuthRepository @Inject constructor(
private val authRemoteDataSource: AuthRemoteDataSource
) : AuthRepository {
override suspend fun postEmail(email: Email): Result<String> {
return authRemoteDataSource.postEmail(email)
}
}
10 changes: 10 additions & 0 deletions data/src/main/java/com/everymeal/data/service/auth/AuthApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.everymeal.data.service.auth

import com.everymeal.data.model.BaseResponse
import com.everymeal.data.model.auth.EmailRequest
import retrofit2.http.POST

interface AuthApi {
@POST("/api/v1/users/email")
suspend fun postEmail(emailRequest: EmailRequest): BaseResponse<String>
}
5 changes: 5 additions & 0 deletions domain/src/main/java/com/everymeal/domain/model/auth/Email.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.everymeal.domain.model.auth

data class Email(
val email: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.everymeal.domain.repository.auth

import com.everymeal.domain.model.auth.Email

interface AuthRepository {
suspend fun postEmail(email: Email): Result<String>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.everymeal.domain.usecase.auth

import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.repository.auth.AuthRepository
import javax.inject.Inject

class PostEmailUseCase @Inject constructor(
private val authRepository: AuthRepository
) {
suspend operator fun invoke(
email: Email
): Result<String> {
return authRepository.postEmail(email)
}
}
8 changes: 3 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -9,18 +9,15 @@ espresso-core = "3.5.1"
lifecycle-runtime-ktx = "2.6.2"
activity = "1.7.2"
compose-bom = "2023.10.01"

dagger-hilt = "2.46.1"
hilt-compose = "1.0.0"

okhttp = "4.11.0"
retrofit = "2.9.0"
serialization = "1.6.0"
kotlin-serilization = "1.0.0"

lottie = "6.1.0"

compose-navigation = "2.7.4"
accompanist = "0.33.0-alpha"

[libraries]
agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
@@ -41,6 +38,7 @@ ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview
ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
material3 = { group = "androidx.compose.material3", name = "material3" }
accompanist-webview = { group = "com.google.accompanist", name = "accompanist-webview", version.ref = "accompanist" }

# Kotlin
kotlin = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
@@ -57,7 +55,7 @@ hilt-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref =

# Retrofit
okhttp-bom = { module = "com.squareup.okhttp3:okhttp-bom", version.ref = "okhttp" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp"}
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }

4 changes: 4 additions & 0 deletions presentation/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ dependencies {
implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview)
implementation(libs.material3)
implementation(libs.accompanist.webview)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
@@ -75,6 +76,9 @@ dependencies {
implementation(libs.hilt.compose)
kapt(libs.hilt.testing.compiler)

// Retrofit
implementation(libs.retrofit)

// Lottie
implementation(libs.compose.lottie)

Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -34,9 +36,11 @@ import com.everymeal.presentation.R
import com.everymeal.presentation.ui.detail.ReportCategoryType
import com.everymeal.presentation.ui.home.HomeCategoryList
import com.everymeal.presentation.ui.theme.EveryMealTypo
import com.everymeal.presentation.ui.theme.EveryMealTypography
import com.everymeal.presentation.ui.theme.Gray200
import com.everymeal.presentation.ui.theme.Gray400
import com.everymeal.presentation.ui.theme.Gray600
import com.everymeal.presentation.ui.theme.Gray700
import com.everymeal.presentation.ui.theme.Gray800
import com.everymeal.presentation.ui.theme.Gray900
import com.everymeal.presentation.ui.theme.Grey2
@@ -49,7 +53,7 @@ import com.everymeal.presentation.ui.theme.Typography
fun EveryMealMainBottomSheetDialog(
title: String,
content: String,
onClick : () -> Unit,
onClick: () -> Unit,
onDismiss: () -> Unit
) {
ModalBottomSheet(
@@ -148,7 +152,7 @@ fun SortCategoryItem(
color = Gray900,
style = EveryMealTypo.displayMedium,
)
if(title == category) {
if (title == category) {
Image(
modifier = Modifier.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.icon_check_mono),
@@ -266,6 +270,7 @@ fun RatingItem(
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EveryMealReportBottomSheetDialog(
@@ -305,6 +310,74 @@ fun EveryMealReportBottomSheetDialog(
}
}

data class EveryMealConditionAgreeDialogItem(
val title: String,
val isAgreed: Boolean,
val isEssential: Boolean = false,
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EveryMealConditionAgreeDialog(
onItemClicked: (Int) -> Unit,
onNextButtonClicked: () -> Unit,
onDismiss: () -> Unit,
conditionItems: List<EveryMealConditionAgreeDialogItem>
) {
ModalBottomSheet(
onDismissRequest = { onDismiss() },
containerColor = Color.White,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
) {
Text(
text = stringResource(R.string.condition_agree_title),
style = EveryMealTypography.Heading2,
color = Gray900,
)
Spacer(modifier = Modifier.size(13.dp))
LazyColumn(content = {
itemsIndexed(conditionItems) {index, item ->
Row(
modifier = Modifier
.clickable(onClick = {
onItemClicked(index)
})
.padding(vertical = 7.dp),
) {
Image(
painter = if (item.isAgreed) painterResource(
id = R.drawable.icon_check_mono
) else painterResource(id = R.drawable.icon_check_gray_mono),
contentDescription = "check"
)
Text(
modifier = Modifier.padding(start = 6.dp),
text = item.title,
style = EveryMealTypography.Subtitle3,
color = Gray700,
)
Spacer(modifier = Modifier.weight(1f))
Image(
painter = painterResource(id = R.drawable.icon_arrow_right),
contentDescription = null
)
}
}
})
EveryMealMainButton(
text = stringResource(R.string.ok),
enabled = true,
onClick = onNextButtonClicked,
)
Spacer(modifier = Modifier.size(24.dp))
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EveryMealDetailReportBottomSheetDialog(
@@ -385,7 +458,7 @@ fun ReportCategoryItem(
modifier = Modifier.size(24.dp),
imageVector = ImageVector.vectorResource(R.drawable.icon_check_gray_mono),
contentDescription = null,
colorFilter = if(title == category) {
colorFilter = if (title == category) {
ColorFilter.tint(Main100)
} else {
ColorFilter.tint(Gray400)
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@ fun EveryMealTextField(
modifier: Modifier = Modifier,
value: String,
onValueChange: (String) -> Unit,
placeholderText: String,
placeholderText: String = "",
isError: Boolean = false,
supportingText: (@Composable () -> Unit)? = null,
leadingIcon: (@Composable () -> Unit)? = null,
otherCustomization: (@Composable () -> Unit)? = null
) {
@@ -28,6 +30,8 @@ fun EveryMealTextField(
value = value,
onValueChange = onValueChange,
leadingIcon = leadingIcon,
isError = isError,
supportingText = supportingText,
placeholder = {
Text(
text = placeholderText,
Original file line number Diff line number Diff line change
@@ -101,4 +101,4 @@ fun MainScreen(
@Composable
fun MainScreenPreview() {
MainScreen()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.everymeal.presentation.ui.signup.school

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.everymeal.presentation.R
import com.everymeal.presentation.components.EveryMealConditionAgreeDialog
import com.everymeal.presentation.components.EveryMealConditionAgreeDialogItem
import com.everymeal.presentation.ui.signup.school.email.SchoolAuthPostEmailScreen
import com.everymeal.presentation.ui.theme.EveryMealTypography

enum class SchoolAuthScreenType {
POST_EMAIL,
VERIFY_TOKEN,
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SchoolAuthScreen(
viewModel: SchoolAuthViewModel = hiltViewModel()
) {
val viewState by viewModel.viewState.collectAsState()
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(id = R.string.school_auth_title),
style = EveryMealTypography.Subtitle2,
)
},
navigationIcon = {
Image(
modifier = Modifier
.size(48.dp)
.padding(12.dp),
painter = painterResource(id = R.drawable.icon_x_mono),
contentDescription = "close"
)
})
}
)
{ innerPadding ->
SchoolAuthContent(
modifier = Modifier
.padding(innerPadding)
.padding(horizontal = 20.dp),
viewModel = viewModel,
state = viewState
)
if (viewState.isShowConditionBottomSheet) {
EmailAuthBottomSheet(viewModel)
}
}
}

@Composable
private fun EmailAuthBottomSheet(viewModel: SchoolAuthViewModel) {
val conditionItems = remember {
mutableStateListOf(
EveryMealConditionAgreeDialogItem(
title = "[필수] 이용 약관 동의",
isAgreed = true,
isEssential = true,
),
EveryMealConditionAgreeDialogItem(
title = "[필수] 개인정보 수집 및 이용 동의",
isAgreed = true,
isEssential = true,
),
EveryMealConditionAgreeDialogItem(
title = "[선택] 마케팅 정보 수집 동의",
isAgreed = true,
)
)
}

EveryMealConditionAgreeDialog(
onItemClicked = {
conditionItems[it] =
conditionItems[it].copy(isAgreed = !conditionItems[it].isAgreed)
},
onNextButtonClicked = {
if (conditionItems.filter { it.isEssential }.any { it.isAgreed }) {
viewModel.setEvent(SchoolContract.Event.OnPostEmail)
}
},
onDismiss = {},
conditionItems = conditionItems
)
}

@Composable
fun SchoolAuthContent(
modifier: Modifier = Modifier,
viewModel: SchoolAuthViewModel,
state: SchoolContract.State
) {
SchoolAuthPostEmailScreen(
modifier = modifier,
viewModel = viewModel,
state = state,
)
}


@Preview
@Composable
fun SchoolAuthScreenPreview() {
SchoolAuthScreen()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.everymeal.presentation.ui.signup.school

import androidx.lifecycle.viewModelScope
import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.usecase.auth.PostEmailUseCase
import com.everymeal.presentation.base.BaseViewModel
import kotlinx.coroutines.launch
import retrofit2.HttpException
import javax.inject.Inject

class SchoolAuthViewModel @Inject constructor(
private val postEmailUseCase: PostEmailUseCase
) :
BaseViewModel<SchoolContract.State, SchoolContract.Effect, SchoolContract.Event>(SchoolContract.State()) {

companion object {
private val EMAIL_REGEX = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex()
}

override fun handleEvents(event: SchoolContract.Event) {
when (event) {
is SchoolContract.Event.OnEmailTextChanged -> {
updateState {
copy(
isEmailError = isValidEmail(event.emailLink),
emailLink = event.emailLink
)
}
}

is SchoolContract.Event.OnNextButtonClicked -> {
updateState {
copy(isShowConditionBottomSheet = true)
}
}

is SchoolContract.Event.OnPostEmail -> {
postEmail()
}

SchoolContract.Event.FailEmailVerification -> {
sendEffect()
}
}
}


private fun isValidEmail(email: String): Boolean {
return EMAIL_REGEX.matches(email)
}

private fun postEmail() {
viewModelScope.launch {
postEmailUseCase(Email(viewState.value.emailLink)).onSuccess {
updateState {
copy(emailAuthToken = it)
}
}.onFailure {
if (it is HttpException) {
sendEffect({ SchoolContract.Effect.Error(it.code()) })
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.everymeal.presentation.ui.signup.school

import com.everymeal.presentation.base.ViewEvent
import com.everymeal.presentation.base.ViewSideEffect
import com.everymeal.presentation.base.ViewState

class SchoolContract {

data class State(
val schoolAuthScreenType: SchoolAuthScreenType = SchoolAuthScreenType.POST_EMAIL,
val isShowConditionBottomSheet: Boolean = false,
val isEmailError: Boolean = false,
val emailLink: String = "",
val emailAuthToken: String = ""
) : ViewState

sealed class Event : ViewEvent {
data class OnEmailTextChanged(val emailLink: String) : Event()
object OnNextButtonClicked : Event()
object OnPostEmail : Event()
object FailEmailVerification : Event()
}

sealed class Effect : ViewSideEffect {
data class Error(val code: Int) : Effect()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.everymeal.presentation.ui.signup.school.email

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.everymeal.presentation.R
import com.everymeal.presentation.components.EveryMealMainButton
import com.everymeal.presentation.components.EveryMealTextField
import com.everymeal.presentation.ui.signup.school.SchoolAuthScreenType
import com.everymeal.presentation.ui.signup.school.SchoolAuthViewModel
import com.everymeal.presentation.ui.signup.school.SchoolContract
import com.everymeal.presentation.ui.theme.EveryMealTypography
import com.everymeal.presentation.ui.theme.Gray100
import com.everymeal.presentation.ui.theme.Gray900
import com.everymeal.presentation.ui.theme.Main100

@Composable
fun SchoolAuthPostEmailScreen(
modifier: Modifier,
state: SchoolContract.State,
viewModel: SchoolAuthViewModel
) {
Column(
modifier = modifier.padding(top = 48.dp)
) {
Text(
text = when (state.schoolAuthScreenType) {
SchoolAuthScreenType.POST_EMAIL -> stringResource(id = R.string.school_auth_content)
SchoolAuthScreenType.VERIFY_TOKEN -> stringResource(id = R.string.email_token_verify_title)
},
style = EveryMealTypography.Heading1,
color = Gray900
)
Spacer(modifier = Modifier.size(40.dp))
Text(
text = when(state.schoolAuthScreenType) {
SchoolAuthScreenType.POST_EMAIL -> stringResource(id = R.string.email)
SchoolAuthScreenType.VERIFY_TOKEN -> stringResource(id = R.string.verify_token)
},
style = EveryMealTypography.Body5,
color = Gray100
)
Spacer(modifier = Modifier.size(6.dp))
EveryMealTextField(
modifier = Modifier.fillMaxWidth(),
value = state.emailLink,
onValueChange = {
viewModel.setEvent(SchoolContract.Event.OnEmailTextChanged(it))
},
supportingText = {
if (state.isEmailError) {
Text(
text = stringResource(id = R.string.email_error),
style = EveryMealTypography.Body5,
color = Main100
)
}
}
)
Spacer(modifier = Modifier.weight(1f))
EveryMealMainButton(
text = stringResource(id = R.string.next),
onClick = {
viewModel.setEvent(SchoolContract.Event.OnNextButtonClicked)
},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.everymeal.presentation.ui.web

import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import com.everymeal.presentation.R
import com.google.accompanist.web.AccompanistWebChromeClient
import com.google.accompanist.web.AccompanistWebViewClient
import com.google.accompanist.web.WebView
import com.google.accompanist.web.WebViewNavigator
import com.google.accompanist.web.rememberWebViewState

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WebScreenContent(
url: String,
staticTitle: String? = null,
webViewNavigator: WebViewNavigator,
onBackPressed: (() -> Unit)? = null,
) {

val webViewState = rememberWebViewState(url = url)

Scaffold(
topBar = {
TopAppBar(
title = { Text(text = staticTitle ?: (webViewState.pageTitle ?: "")) },
navigationIcon = {
onBackPressed?.let {
Image(
modifier = Modifier.clickable {
if (webViewNavigator.canGoBack) webViewNavigator.navigateBack()
else onBackPressed()
},
painter = painterResource(id = R.drawable.icon_arrow_back_mono),
contentDescription = "back"
)
}
}
)
}
) { innerPadding ->
WebView(
state = webViewState,
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
navigator = webViewNavigator,
onCreated = { webView ->
webView.settings.javaScriptEnabled = true
},
client = remember { AccompanistWebViewClient() },
chromeClient = remember { AccompanistWebChromeClient() }
)
}

}
13 changes: 12 additions & 1 deletion presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -7,6 +7,10 @@
<string name="ok">확인</string>
<string name="close">닫기</string>
<string name="exit">나가기</string>
<string name="next">다음</string>
<string name="email">이메일</string>
<string name="verify_token">인증번호</string>
<string name="email_error">잘못된 이메일 형식이에요</string>

<!-- 로그인, 온보딩, 대학선택화면 -->
<string name="univ_select_title">반가워요!\n대학을 선택해주세요</string>
@@ -98,7 +102,6 @@
<string name="what_food_everymeal_ready">빠른 시일 내에 이용하실 수 있도록\n에브리밀이 준비하고 있어요.</string>

<!-- 온보딩화면 -->
<string name="next">다음</string>
<string name="onboarding_today_what_food">우리 오늘 뭐먹지?</string>
<string name="onboarding_school_food">학식에서\n학교 주변 맛집까지</string>
<string name="onboarding_everymeal">에브리밀에서\n간편하게</string>
@@ -116,6 +119,14 @@
<string name="my_page_my_activities">나의 활동</string>
<string name="my_page_settings">설정</string>

<!-- 학교 인증 화면 -->
<string name="school_auth_title">학교 인증</string>
<string name="school_auth_content">학교 인증을 위해\n대학 메일을 입력해주세요</string>
<string name="condition_agree_title">이용을 위한 동의가 필요해요</string>
<string name="condition_agree">[필수] 이용 약관 동의</string>
<string name="email_token_verify_title">메일로 전달받은\n인증번호를 입력해주세요</string>


<!-- 에러다이얼로그 -->
<string name="error_dialog_title">네트워크에 연결할 수 없어요</string>
<string name="error_dialog_content">네트워크 연결 상태 확인 후 다시 시도해주세요</string>

0 comments on commit b38640b

Please sign in to comment.