Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 4주차 과제 #8

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
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
20 changes: 20 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import java.util.Properties

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}

val properties = Properties().apply {
load(project.rootProject.file("local.properties").inputStream())
}

android {
namespace = "org.sopt.and"
compileSdk = 34
Expand All @@ -17,6 +23,8 @@ android {
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("String", "BASE_URL", properties["base.url"].toString())
}

buildTypes {
Expand All @@ -37,6 +45,7 @@ android {
}
buildFeatures {
compose = true
buildConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.0"
Expand Down Expand Up @@ -70,4 +79,15 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.collections.immutable)

// Network
implementation(platform(libs.okhttp.bom))
implementation(libs.okhttp)
implementation(libs.okhttp.logging.interceptor)
implementation(libs.retrofit)
implementation(libs.retrofit.kotlin.serialization.converter)
implementation(libs.kotlinx.serialization.json)
implementation(libs.retrofit.v2110)
implementation(libs.converter.gson)
Comment on lines +82 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bundle을 사용해보셔도 좋을 것 같슴다 ~

implementation(libs.coil.compose)

}
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -11,6 +13,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ANDANDROID"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".presentation.main.MainActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.and.data.datalocal.datasource

interface UserInfoLocalDataSource {
var accessToken: String
var nickname: String
fun clear()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import org.sopt.and.data.datalocal.datasource.UserInfoLocalDataSource

class UserInfoLocalDataSourceImpl(context: Context) : UserInfoLocalDataSource {

private val sharedPreferences: SharedPreferences =
context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)

override var accessToken: String
get() = sharedPreferences.getString(TOKEN, INITIAL_VALUE).toString()
set(value) = sharedPreferences.edit { putString(TOKEN, value) }

override var nickname: String
get() = sharedPreferences.getString(NICKNAME, INITIAL_VALUE).toString()
set(value) = sharedPreferences.edit { putString(NICKNAME, value) }

override fun clear() = sharedPreferences.edit { clear() }

companion object {
const val PREFERENCES_NAME = "user_preferences"
const val TOKEN = "token"
const val NICKNAME = "nickname"
const val INITIAL_VALUE = ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.model.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RequestLoginDto(
@SerialName("username")
val username: String,
@SerialName("password")
val password: String
)


Comment on lines +13 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2줄 !

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.model.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RequestSignUpDto(
@SerialName("username")
val username: String,
@SerialName("password")
val password: String,
@SerialName("hobby")
val hobby: String
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 Result에 해당하는 부분 data class를 아예 외부에 분리해서 짰었는데 뭔가 기능상에 차이점이 있나요?? 이 방식이 가독성 측면에선 훨씬 좋은 것 같아보이네요

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.and.data.model.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable


Comment on lines +5 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2줄 !

@Serializable
data class ResponseLoginDto(
@SerialName("result")
val result: Result
) {
Comment on lines +7 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분이 계속 공통되는 것 같은데 BaseResponse를 사용하시는 것도 방법이 될 것 같네요!

@Serializable
data class Result(
@SerialName("token")
val token: String
)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 Result를 아예 밖에 분리하는 거랑 앞처럼 본문 안에 써주는거랑 차이점이 있는지 궁금합니다!!

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.and.data.model.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseMyHobbyDto(
@SerialName("result")
val result: Result? = null,
@SerialName("code")
val code: String? = null
)

@Serializable
data class Result(
@SerialName("hobby")
val hobby: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.sopt.and.data.model.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseFailedDto(
@SerialName("code")
val code: String
)

@Serializable
data class ResponseSignUpDto(
@SerialName("result")
val result: Result
) {
@Serializable
data class Result(
@SerialName("no")
val no: Int
)
}

21 changes: 21 additions & 0 deletions app/src/main/java/org/sopt/and/data/service/RetrofitInstance.kt

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 Gson사용으로 바꿔봐야 겠어요

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.sopt.and.data.service

import org.sopt.and.BuildConfig
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitInstance {
private const val BASE_URL = BuildConfig.BASE_URL

private val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

왜 Gson을 사용하신 건지 여쭤봐두 되나염?

.build()
}

val userService: UserService by lazy {
retrofit.create(UserService::class.java)
}
}

28 changes: 28 additions & 0 deletions app/src/main/java/org/sopt/and/data/service/UserService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sopt.and.data.service

import org.sopt.and.data.model.request.RequestLoginDto
import org.sopt.and.data.model.request.RequestSignUpDto
import org.sopt.and.data.model.response.ResponseLoginDto
import org.sopt.and.data.model.response.ResponseMyHobbyDto
import org.sopt.and.data.model.response.ResponseSignUpDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST


interface UserService {
@POST("/user")
suspend fun postSignup(@Body requestDto: RequestSignUpDto): Response<ResponseSignUpDto>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

응답 타입이 늘 ResponseSignUpDto로 설정되어 있는데, 응답이 실패한 경우에는 어떻게 FailedDTO를 반환할 수 있는 건가요?? 저도 성공/실패 DTO를 구분했었는데, 이 부분에 반환값을 늘 성공한 경우 DTO로 줘도 되는 건지 헷갈리더라구요 ..


@POST("/login")
suspend fun postLogin(@Body requestDto: RequestLoginDto): Response<ResponseLoginDto>


@GET("/user/my-hobby")
suspend fun getUserHobby(
@Header("token") token: String
): Response<ResponseMyHobbyDto>

}
3 changes: 2 additions & 1 deletion app/src/main/java/org/sopt/and/domain/User.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package org.sopt.and.domain

data class User(
var email: String = "",
var password: String = ""
var password: String = "",
var hobby: String = ""
Comment on lines 4 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var로 선언하신 이유가 있나요?

)
18 changes: 12 additions & 6 deletions app/src/main/java/org/sopt/and/presentation/component/TextField.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ import androidx.compose.ui.unit.dp
import org.sopt.and.R

@Composable
fun EmailTextField(
userEmail: MutableState<String>,
fun BaseTextField(
text: MutableState<String>,
placeHolder: String,
onValueChange: (String) -> Unit = {},
modifier: Modifier = Modifier
) {
val containerColor = Color(0xFF2F2F2F)
OutlinedTextField(
modifier = modifier.fillMaxWidth(),
value = userEmail.value,
value = text.value,
onValueChange = { newValue ->
userEmail.value = newValue
text.value = newValue
onValueChange(newValue)
},
placeholder = {
Expand Down Expand Up @@ -112,17 +112,23 @@ fun PasswordTextField(
private fun TextFieldPreview() {
val userEmail = remember { mutableStateOf("") }
val userPassword = remember { mutableStateOf("") }
val userHobby = remember { mutableStateOf("") }
val passwordVisible = remember { mutableStateOf(false) }

Column {
EmailTextField(
userEmail = userEmail,
BaseTextField(
text = userEmail,
placeHolder = stringResource(id = R.string.sign_up_email_placeholder)
)

PasswordTextField(
userPassword = userPassword,
passwordVisible = passwordVisible,
placeHolder = stringResource(id = R.string.sign_up_password_placeholder)
)
BaseTextField(
text = userHobby,
placeHolder = stringResource(id = R.string.sign_up_hobby_placeholder)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import org.sopt.and.ImageRatio.LARGE
import org.sopt.and.ImageRatio.SMALL
import org.sopt.and.R
import org.sopt.and.util.ImageRatio.LARGE
import org.sopt.and.util.ImageRatio.SMALL

@Composable
fun HomeViewLazyRow(images: ImmutableList<Int>, modifier: Modifier = Modifier) {
Expand Down
31 changes: 28 additions & 3 deletions app/src/main/java/org/sopt/and/presentation/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,43 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.navigation.compose.rememberNavController
import org.sopt.and.presentation.navigation.BottomNavigationBar
import org.sopt.and.presentation.navigation.NavGraph
import org.sopt.and.ui.theme.ANDANDROIDTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()

setContent {
ANDANDROIDTheme {
MainScreen()
val navController = rememberNavController()
var bottomNaviVisible by remember { mutableStateOf(false) }

Scaffold(bottomBar = {
if (bottomNaviVisible) {
BottomNavigationBar(
navController = navController
)
}
}) { innerPadding: PaddingValues ->
NavGraph(
navController = navController,
isLogined = { bottomNaviVisible = it },
Modifier.padding(innerPadding)
)
}
}
}
}
}


Loading