Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
cda17c8
apply MVVM architecture
tunaunnie Nov 12, 2024
113b9fa
api connecting
tunaunnie Nov 15, 2024
71d677f
[feat] ์œ ์ € ๋“ฑ๋ก API ์—ฐ๋™
tunaunnie Nov 15, 2024
ee9d131
feature #week4 : ํšŒ์›๊ฐ€์ž… ํ†ต์‹  ์„ฑ๊ณต
tunaunnie Dec 3, 2024
841d04e
fix #week4 : signup ํ›„ login ์ด๋™ ์‹œ navigate ๋กœ์ง ์ˆ˜์ •
tunaunnie Dec 3, 2024
72b791b
fix #week4 : ๋„ค์ด๊ฒŒ์ด์…˜ ํด๋”๋ง ๊ตฌ์กฐ ์ˆ˜์ •
tunaunnie Dec 3, 2024
5cbd2ee
feat #week4 : login Get API ๊ตฌํ˜„ ์™„๋ฃŒ
tunaunnie Dec 3, 2024
18cd80e
feat #week4 : ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ๋„ค๋น„๊ฒŒ์ด์…˜
tunaunnie Dec 3, 2024
26c22c1
feat #week4 : ์ทจ๋ฏธ ์กฐํšŒ API ์—ฐ๊ฒฐ
tunaunnie Dec 3, 2024
0512b01
fix #week4 : NavHost ์ „์ฒด innerPadding ์ œ๊ฑฐ
tunaunnie Dec 3, 2024
f6f4b09
fix #week4 : BaseUrl ์ˆจ๊ธฐ๊ธฐ
tunaunnie Dec 3, 2024
32230ce
initial commit
tunaunnie Dec 3, 2024
20ecf8f
fix #week6 : ํด๋” ๊ตฌ์กฐ ๋ณ€๊ฒฝ
tunaunnie Dec 3, 2024
c3ff78e
fix #week6 : DTO request ์ธ์ž ์ด๋ฆ„ ๋ณ€๊ฒฝ
tunaunnie Dec 3, 2024
51c3193
fix #week6 : baseurl ์ˆจ๊ธฐ๊ธฐ
tunaunnie Dec 8, 2024
4f4f579
feature #week7 : home ๋ฐ login ํ™”๋ฉด contract ๊ตฌํ˜„
tunaunnie Dec 17, 2024
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
28 changes: 25 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
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)
alias(libs.plugins.dagger.hilt)
id("org.jetbrains.kotlin.kapt")
}

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

android {
namespace = "org.sopt.and"
compileSdk = 34
compileSdk = 35

defaultConfig {
applicationId = "org.sopt.and"
minSdk = 28
targetSdk = 34
targetSdk = 35
versionCode = 1
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
}
}

Expand Down Expand Up @@ -65,4 +74,17 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
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.bundles.hilt)
kapt(libs.hilt.compiler)
}

hilt {
enableAggregatingTask = false
}
24 changes: 5 additions & 19 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<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:name=".MyApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -11,26 +14,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ANDANDROID"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MyActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".HomeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SearchActivity"
android:exported="false" />

<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
132 changes: 67 additions & 65 deletions app/src/main/java/org/sopt/and/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,98 +1,100 @@
package org.sopt.and

import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import org.sopt.and.ui.theme.ANDANDROIDTheme
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.HiltAndroidApp
import org.sopt.and.presentation.loginScreen.LoginScreen
import org.sopt.and.presentation.mypageScreen.MypageScreen
import org.sopt.and.presentation.searchScreen.SearchScreen
import org.sopt.and.presentation.signupScreen.SignUpScreen
import org.sopt.and.presentation.homeScreen.HomeScreen
import org.sopt.and.presentation.homeScreen.HomeViewModel
import org.sopt.and.presentation.loginScreen.LoginViewModel
import org.sopt.and.presentation.mypageScreen.MypageViewModel
import org.sopt.and.util.Route

//๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ๋กœ๊ทธ์ธํ•œ ์ด๋ฉ”์ผ์„ viewmodel์— ๋‹ด์•„ ์ „์—ญ๋ณ€์ˆ˜๋กœ ๊ด€๋ฆฌ..
class UserViewModel : ViewModel() {

private val _email = MutableLiveData<String>()
val email: LiveData<String> = _email

fun setEmail(newEmail: String) {
_email.value = newEmail
}
}

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
ANDANDROIDTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
val navController = rememberNavController()
val userViewModel: UserViewModel = viewModel()
Scaffold(
modifier = Modifier.fillMaxSize(),
content = { it
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = SignUpScreen,
modifier = Modifier.padding(innerPadding)
){
composable<SignUpScreen> {
SignUpScreen(
navigateToLoginScreen = {
emailText, passwordText -> navController.navigate(LoginScreen(emailText, passwordText))
}
)
}
val context = navController.context

composable<LoginScreen> { backStackEntry ->
val item = backStackEntry.toRoute<LoginScreen>()
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
LoginScreen(
emailText = item.emailText,
passwordText = item.passwordText,
scope = scope,
snackbarHostState = snackbarHostState,
navigateToHomeScreen = {
navController.navigate("home")
}
)
}
NavHost(
navController = navController,
startDestination = Route.SignUpScreen(userName = "", password = ""),
modifier = Modifier
){
composable<Route.SignUpScreen> { backStackEntry ->
val item = backStackEntry.toRoute<Route.SignUpScreen>()
SignUpScreen(
navigateToLoginScreen = {
navController.navigate(Route.LoginScreen){
popUpTo<Route.SignUpScreen> { inclusive = true }
launchSingleTop = true
}
}
)
}

composable("home") {
HomeScreen(
navController = navController,
)
}
composable<Route.LoginScreen> { backStackEntry ->
val item = backStackEntry.toRoute<Route.LoginScreen>()
LoginScreen(
navigateToHomeScreen = {
navController.navigate(Route.HomeScreen){
popUpTo<Route.HomeScreen> { inclusive = true}
launchSingleTop = true
}
},
)
}

composable("search") {
SearchScreen(
navController = navController
)
}
composable<Route.HomeScreen> { backStackEntry ->
val item = backStackEntry.toRoute<Route.HomeScreen>()
HomeScreen(
homeViewModel = HomeViewModel(),
navController = navController,
)
}

composable("profile") {
composable<Route.SearchScreen> { backStackEntry ->
val item = backStackEntry.toRoute<Route.SearchScreen>()
SearchScreen(
navController = navController
)
}

MypageScreen(
navController = navController,
userViewModel = userViewModel
)
composable<Route.MypageScreen> { backStackEntry ->
val item = backStackEntry.toRoute<Route.MypageScreen>()
MypageScreen(
navController = navController
)
}
}

}
}

})
}
}
}
}

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

import android.app.Application
import dagger.hilt.android.HiltAndroidApp


@HiltAndroidApp
class MyApp : Application()
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 userName: String
fun clear()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sopt.and.data.datalocal.datasourceimpl

import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import dagger.hilt.android.qualifiers.ApplicationContext
import org.sopt.and.data.datalocal.datasource.UserInfoLocalDataSource
import javax.inject.Inject

class UserInfoLocalDataSourceImpl @Inject constructor(
@ApplicationContext private val context: Context
) : UserInfoLocalDataSource {
private val sharedPreferences: SharedPreferences =
context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)

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

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

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

companion object {
const val PREFERENCES_NAME = "user_preferences"
const val ACCESSTOKEN = "accesstoken"
const val USERNAME = "userName"
const val INITIAL_VALUE = ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.and.data.dataremote.datasource

import org.sopt.and.data.dataremote.model.request.RequestCreateUserDto
import org.sopt.and.data.dataremote.model.request.RequestGetUserDto
import org.sopt.and.data.dataremote.model.response.ResponseCreateUserSuccessDto
import org.sopt.and.data.dataremote.model.response.ResponseGetUserDto
import org.sopt.and.data.dataremote.model.response.ResponseGetUserHobbyDto
import org.sopt.and.data.dataremote.model.response.ResponseGetUserHobbyFailDto
import retrofit2.Response

interface UserInfoRemoteDataSource {
suspend fun postSignup(requestCreateUserDto: RequestCreateUserDto): Response<ResponseCreateUserSuccessDto>

suspend fun postLogin(requestGetUserDto: RequestGetUserDto): Response<ResponseGetUserDto>

suspend fun getUserHobby(token: String): Response<ResponseGetUserHobbyDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.sopt.and.data.dataremote.datasourceimpl

import org.sopt.and.data.dataremote.datasource.UserInfoRemoteDataSource
import org.sopt.and.data.dataremote.model.request.RequestCreateUserDto
import org.sopt.and.data.dataremote.model.request.RequestGetUserDto
import org.sopt.and.data.dataremote.model.response.ResponseCreateUserSuccessDto
import org.sopt.and.data.dataremote.model.response.ResponseGetUserDto
import org.sopt.and.data.dataremote.model.response.ResponseGetUserHobbyDto
import org.sopt.and.data.dataremote.network.UserService
import retrofit2.Response
import javax.inject.Inject

class UserInfoRemoteDataSourceImpl @Inject constructor (
private val service: UserService
) : UserInfoRemoteDataSource {
override suspend fun postSignup(requestCreateUserDto: RequestCreateUserDto): Response<ResponseCreateUserSuccessDto> =
service.signUpUser(requestCreateUserDto)

override suspend fun postLogin(requestGetUserDto: RequestGetUserDto): Response<ResponseGetUserDto> =
service.logInUser(requestGetUserDto)

override suspend fun getUserHobby(token: String): Response<ResponseGetUserHobbyDto> =
service.getMyHobby(token)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.dataremote.model.request

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

@Serializable
data class RequestCreateUserDto(
@SerialName("username")
val userName: String,
@SerialName("password")
val password: String,
@SerialName("hobby")
val hobby: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.and.data.dataremote.model.request

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

@Serializable
data class RequestGetUserDto(
@SerialName("username")
val userName: String,
@SerialName("password")
val password: String
)
Loading