diff --git a/app/src/main/java/com/stslex/aproselection/ui/MainActivity.kt b/app/src/main/java/com/stslex/aproselection/ui/MainActivity.kt index 6a44d46..9a3d5cb 100644 --- a/app/src/main/java/com/stslex/aproselection/ui/MainActivity.kt +++ b/app/src/main/java/com/stslex/aproselection/ui/MainActivity.kt @@ -1,14 +1,35 @@ package com.stslex.aproselection.ui import android.os.Bundle +import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.lifecycle.lifecycleScope +import com.stslex.aproselection.core.datastore.AppDataStore +import com.stslex.aproselection.core.network.client.NetworkClient import com.stslex.aproselection.core.ui.theme.AppTheme +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import org.koin.android.ext.android.inject class MainActivity : ComponentActivity() { + val dataStore by inject() + val networkClient by inject() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + dataStore.token + .catch { + Log.e(it.message, javaClass.simpleName, it) + } + .onEach { + if (it.isBlank()) { + networkClient.regenerateToken() + } + } + .launchIn(lifecycleScope) setContent { AppTheme { InitialApp() diff --git a/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClient.kt b/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClient.kt index a5b97db..83fedd9 100644 --- a/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClient.kt +++ b/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClient.kt @@ -7,4 +7,6 @@ interface NetworkClient { val client: HttpClient val apiClient: HttpClient + + suspend fun regenerateToken() } \ No newline at end of file diff --git a/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClientImpl.kt b/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClientImpl.kt index b7aa353..c10685f 100644 --- a/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClientImpl.kt +++ b/core/network/src/main/java/com/stslex/aproselection/core/network/client/NetworkClientImpl.kt @@ -16,9 +16,11 @@ import io.ktor.client.plugins.logging.Logger import io.ktor.client.plugins.logging.Logging import io.ktor.client.request.bearerAuth import io.ktor.client.request.get +import io.ktor.http.ContentType import io.ktor.http.HttpStatusCode import io.ktor.http.URLProtocol import io.ktor.http.appendPathSegments +import io.ktor.http.contentType import io.ktor.http.encodedPath import io.ktor.serialization.kotlinx.json.json import kotlinx.coroutines.CoroutineScope @@ -98,13 +100,14 @@ class NetworkClientImpl( headers.append("API_KEY", BuildConfig.API_KEY) headers.append("DEVICE_ID", "test") headers.append("uuid", uuid.value) + contentType(ContentType.Application.Json) } bearerAuth(token = token.value) } } - private suspend fun regenerateToken() { - val token = client + override suspend fun regenerateToken() { + val token = apiClient .get { url.appendPathSegments("token") } diff --git a/core/network/src/main/java/com/stslex/aproselection/core/network/clients/auth/AuthNetworkClientImpl.kt b/core/network/src/main/java/com/stslex/aproselection/core/network/clients/auth/AuthNetworkClientImpl.kt index 2fe126c..2ee7d23 100644 --- a/core/network/src/main/java/com/stslex/aproselection/core/network/clients/auth/AuthNetworkClientImpl.kt +++ b/core/network/src/main/java/com/stslex/aproselection/core/network/clients/auth/AuthNetworkClientImpl.kt @@ -6,6 +6,7 @@ import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponse import com.stslex.aproselection.core.network.clients.auth.model.UserAuthSendModel import io.ktor.client.call.body import io.ktor.client.request.get +import io.ktor.client.request.post import io.ktor.client.request.setBody import io.ktor.http.appendPathSegments import kotlinx.coroutines.Dispatchers @@ -35,9 +36,9 @@ class AuthNetworkClientImpl( ): Flow = flow { val result = networkClient .apiClient - .get { + .post { url.appendPathSegments("passport/auth") - setBody(user) + setBody(user) } .body() emit(result) @@ -49,9 +50,9 @@ class AuthNetworkClientImpl( ): Flow = flow { val result = networkClient .apiClient - .get { + .post { url.appendPathSegments("passport/register") - setBody(user) + setBody(user) } .body() emit(result) diff --git a/feature/auth/build.gradle.kts b/feature/auth/build.gradle.kts index 4c98180..99a9ff4 100644 --- a/feature/auth/build.gradle.kts +++ b/feature/auth/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation(project(":core:ui")) + implementation(project(":core:datastore")) implementation(project(":core:network")) } diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/AuthMapper.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/AuthMapper.kt new file mode 100644 index 0000000..bd9ba83 --- /dev/null +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/AuthMapper.kt @@ -0,0 +1,12 @@ +package com.stslex.aproselection.feature.auth.data.model + +import com.stslex.aproselection.core.network.clients.auth.model.UserAuthResponseModel + +object AuthMapper { + + fun UserAuthResponseModel.toData(): UserModel = UserModel( + uuid = uuid, + username = username, + nickname = nickname + ) +} \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/UserModel.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/UserModel.kt new file mode 100644 index 0000000..3619855 --- /dev/null +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/model/UserModel.kt @@ -0,0 +1,7 @@ +package com.stslex.aproselection.feature.auth.data.model + +data class UserModel( + val uuid: String, + val username: String, + val nickname: String, +) diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepository.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepository.kt index 5b77795..69942ef 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepository.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepository.kt @@ -1,8 +1,11 @@ package com.stslex.aproselection.feature.auth.data.repository +import com.stslex.aproselection.feature.auth.data.model.UserModel import kotlinx.coroutines.flow.Flow interface AuthRepository { - fun getHello(username: String): Flow + fun auth(username: String, password: String): Flow + + fun register(username: String, password: String): Flow } \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepositoryImpl.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepositoryImpl.kt index 8760b92..a46d124 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -1,17 +1,45 @@ package com.stslex.aproselection.feature.auth.data.repository +import com.stslex.aproselection.core.datastore.AppDataStore import com.stslex.aproselection.core.network.clients.auth.AuthNetworkClient +import com.stslex.aproselection.core.network.clients.auth.model.UserAuthSendModel +import com.stslex.aproselection.feature.auth.data.model.AuthMapper.toData +import com.stslex.aproselection.feature.auth.data.model.UserModel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach class AuthRepositoryImpl( - private val networkClient: AuthNetworkClient + private val networkClient: AuthNetworkClient, + private val dataSource: AppDataStore ) : AuthRepository { - override fun getHello(username: String): Flow = flow { - val helloResponse = networkClient - .getHello(username = username) - .text - emit(helloResponse) - } + + override fun auth( + username: String, + password: String + ): Flow = networkClient.auth( + UserAuthSendModel(username, password) + ) + .onEach { response -> + dataSource.setToken(response.token) + dataSource.setUuid(response.uuid) + } + .map { user -> + user.toData() + } + + override fun register( + username: String, + password: String + ): Flow = networkClient.register( + UserAuthSendModel(username, password) + ) + .onEach { response -> + dataSource.setToken(response.token) + dataSource.setUuid(response.uuid) + } + .map { user -> + user.toData() + } } \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractor.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractor.kt index 0629d66..e5a2355 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractor.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractor.kt @@ -1,8 +1,11 @@ package com.stslex.aproselection.feature.auth.domain.interactor +import com.stslex.aproselection.feature.auth.data.model.UserModel import kotlinx.coroutines.flow.Flow interface AuthInteractor { - fun getHello(username: String): Flow + fun auth(username: String, password: String): Flow + + fun register(username: String, password: String): Flow } \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractorImpl.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractorImpl.kt index d696509..e62839b 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractorImpl.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/domain/interactor/AuthInteractorImpl.kt @@ -1,5 +1,6 @@ package com.stslex.aproselection.feature.auth.domain.interactor +import com.stslex.aproselection.feature.auth.data.model.UserModel import com.stslex.aproselection.feature.auth.data.repository.AuthRepository import kotlinx.coroutines.flow.Flow @@ -7,9 +8,19 @@ class AuthInteractorImpl( private val repository: AuthRepository ) : AuthInteractor { - override fun getHello( - username: String - ): Flow = repository.getHello( - username = username + override fun auth( + username: String, + password: String + ): Flow = repository.auth( + username = username, + password = password + ) + + override fun register( + username: String, + password: String + ): Flow = repository.register( + username = username, + password = password ) } \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthScreen.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthScreen.kt index 3c29bac..5da2af8 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthScreen.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthScreen.kt @@ -25,13 +25,17 @@ import com.stslex.aproselection.core.ui.navigation.NavigationScreen fun AuthScreen( text: String, navigate: (NavigationScreen) -> Unit, - setUsername: (String) -> Unit, + auth: (String, String) -> Unit, modifier: Modifier = Modifier, ) { var inputUsername by remember { mutableStateOf("") } + var inputPassword by remember { + mutableStateOf("") + } + Box( modifier = modifier .fillMaxSize() @@ -52,9 +56,19 @@ fun AuthScreen( maxLines = 1, ) Divider(Modifier.padding(16.dp)) + TextField( + value = inputPassword, + onValueChange = { value -> + if (inputPassword != value) { + inputPassword = value + } + }, + maxLines = 1, + ) + Divider(Modifier.padding(16.dp)) ElevatedButton( onClick = { - setUsername(inputUsername) + auth(inputUsername, inputPassword) inputUsername = "" } ) { @@ -73,12 +87,12 @@ fun AuthScreen( } } -@Preview(device = "id:pixel_6", showSystemUi = true, showBackground = true) -@Composable -fun AuthScreenPreview() { - AuthScreen( - text = "text", - navigate = {}, - setUsername = {} - ) -} \ No newline at end of file +//@Preview(device = "id:pixel_6", showSystemUi = true, showBackground = true) +//@Composable +//fun AuthScreenPreview() { +// AuthScreen( +// text = "text", +// navigate = {}, +// setUsername = {} +// ) +//} \ No newline at end of file diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthViewModel.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthViewModel.kt index 4fc3873..ecb9ab3 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthViewModel.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/AuthViewModel.kt @@ -19,14 +19,20 @@ class AuthViewModel( val text: StateFlow get() = _text.asStateFlow() - fun setUsername(username: String) { + fun auth(username: String, password: String) { _text.value = "..." - interactor.getHello(username) + + interactor + .register( + username = username, + password = password + ) .catch { throwable -> + _text.emit("Error: ${throwable.localizedMessage}") handleError(throwable) } - .onEach { receivedText -> - _text.emit(receivedText) + .onEach { userModel -> + _text.emit("Success: uuid--${userModel.uuid}") } .launchIn(viewModelScope) } diff --git a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/navigation/AuthRouter.kt b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/navigation/AuthRouter.kt index 557bbd3..3273528 100644 --- a/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/navigation/AuthRouter.kt +++ b/feature/auth/src/main/java/com/stslex/aproselection/feature/auth/ui/navigation/AuthRouter.kt @@ -28,7 +28,7 @@ fun NavGraphBuilder.authRouter( AuthScreen( text = text, navigate = navigate, - setUsername = viewModel::setUsername, + auth = viewModel::auth, modifier = modifier ) }