From 7ed9f6cc052adec17817f383f720f34b20a8ee24 Mon Sep 17 00:00:00 2001 From: bhindor Date: Thu, 5 Feb 2026 19:55:41 +0900 Subject: [PATCH 01/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20add=20login=20f?= =?UTF-8?q?ile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚡️ :: binding setting --- app/build.gradle.kts | 3 +++ app/src/main/AndroidManifest.xml | 3 +++ .../mumu/presentation/login/LoginActivity.kt | 26 +++++++++++++++++++ app/src/main/res/layout/activity_login.xml | 10 +++++++ 4 files changed, 42 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt create mode 100644 app/src/main/res/layout/activity_login.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f851d74..ef978e3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -33,6 +33,9 @@ android { kotlinOptions { jvmTarget = "11" } + buildFeatures { + viewBinding = true + } } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b224e33..082a259 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,9 @@ android:supportsRtl="true" android:theme="@style/Theme.Mumu" tools:targetApi="31"> + diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt new file mode 100644 index 0000000..a90bb03 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -0,0 +1,26 @@ +package kr.ac.anu.mumu.presentation.login + +import android.os.Bundle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import kr.ac.anu.mumu.R +import kr.ac.anu.mumu.databinding.ActivityLoginBinding + +class LoginActivity : AppCompatActivity() { + + private lateinit var binding: ActivityLoginBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) + insets + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..2bea84e --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file From 44cfdb5de0400e2db922a8804becdd9f9c0dfa4e Mon Sep 17 00:00:00 2001 From: bhindor Date: Thu, 5 Feb 2026 22:16:41 +0900 Subject: [PATCH 02/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20sdk=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- app/src/main/AndroidManifest.xml | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef978e3..a681628 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,11 +5,11 @@ plugins { android { namespace = "kr.ac.anu.mumu" - compileSdk = 35 + compileSdk = 36 defaultConfig { applicationId = "kr.ac.anu.mumu" - minSdk = 24 + minSdk = 26 targetSdk = 35 versionCode = 1 versionName = "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 082a259..4d54553 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,16 +14,17 @@ tools:targetApi="31"> - + android:exported="true" > + + \ No newline at end of file From 3d16dd16e95954f922209508c282ec81aca31a69 Mon Sep 17 00:00:00 2001 From: bhindor Date: Thu, 5 Feb 2026 22:16:52 +0900 Subject: [PATCH 03/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20main=20title=20?= =?UTF-8?q?view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mumu/presentation/login/LoginActivity.kt | 28 +++++++++++++++++++ app/src/main/res/layout/activity_login.xml | 13 +++++++++ 2 files changed, 41 insertions(+) diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt index a90bb03..9a96d22 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -1,8 +1,12 @@ package kr.ac.anu.mumu.presentation.login import android.os.Bundle +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.style.ForegroundColorSpan import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import kr.ac.anu.mumu.R @@ -22,5 +26,29 @@ class LoginActivity : AppCompatActivity() { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } + + viewSet() + } + + private fun viewSet() { + val originText = binding.tvTitle.text.toString() + val spannable = SpannableStringBuilder(originText) + + val targetWord = "Mumu" + val start = originText.indexOf(targetWord) + val end = start + targetWord.length + + if (start != -1) { + val color = ContextCompat.getColor(this, R.color.mumumint_300) + + spannable.setSpan( + ForegroundColorSpan(color), + start, + end, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + binding.tvTitle.text = spannable } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 2bea84e..3255803 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -7,4 +7,17 @@ android:layout_height="match_parent" tools:context=".presentation.login.LoginActivity"> + + \ No newline at end of file From a8d3989eb74db2522fb9d9d29d75fb80bd27d52c Mon Sep 17 00:00:00 2001 From: bhindor Date: Fri, 6 Feb 2026 18:08:38 +0900 Subject: [PATCH 04/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20id=20pw=20edit?= =?UTF-8?q?=20box?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/drawable/gray_edit_box.xml | 5 ++++ app/src/main/res/layout/activity_login.xml | 32 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 app/src/main/res/drawable/gray_edit_box.xml diff --git a/app/src/main/res/drawable/gray_edit_box.xml b/app/src/main/res/drawable/gray_edit_box.xml new file mode 100644 index 0000000..b9136e6 --- /dev/null +++ b/app/src/main/res/drawable/gray_edit_box.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 3255803..828db1a 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -20,4 +20,36 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + + \ No newline at end of file From be5a0402f663c645e4737893b571072e81a92c1e Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 08:30:40 +0900 Subject: [PATCH 05/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20login=20btn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/drawable/btn_disabled.xml | 8 ++++++++ app/src/main/res/drawable/btn_enabled.xml | 8 ++++++++ app/src/main/res/drawable/btn_selector.xml | 5 +++++ app/src/main/res/layout/activity_login.xml | 15 +++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 app/src/main/res/drawable/btn_disabled.xml create mode 100644 app/src/main/res/drawable/btn_enabled.xml create mode 100644 app/src/main/res/drawable/btn_selector.xml diff --git a/app/src/main/res/drawable/btn_disabled.xml b/app/src/main/res/drawable/btn_disabled.xml new file mode 100644 index 0000000..375755b --- /dev/null +++ b/app/src/main/res/drawable/btn_disabled.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/btn_enabled.xml b/app/src/main/res/drawable/btn_enabled.xml new file mode 100644 index 0000000..3fce4ed --- /dev/null +++ b/app/src/main/res/drawable/btn_enabled.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/btn_selector.xml b/app/src/main/res/drawable/btn_selector.xml new file mode 100644 index 0000000..c876632 --- /dev/null +++ b/app/src/main/res/drawable/btn_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 828db1a..8a406a0 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -52,4 +52,19 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/et_id" /> + + \ No newline at end of file From b6986a78642d738ae0be0b14e7aeefc7638e459d Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 14:53:31 +0900 Subject: [PATCH 06/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20viewModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 로그인 뷰모델 및 기초 동작 세팅 --- .../ac/anu/mumu/presentation/login/LoginActivity.kt | 13 +++++++++++++ .../anu/mumu/presentation/login/LoginViewModel.kt | 10 ++++++++++ 2 files changed, 23 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt index 9a96d22..287271e 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -5,6 +5,7 @@ import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat @@ -15,6 +16,7 @@ import kr.ac.anu.mumu.databinding.ActivityLoginBinding class LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding + private val viewModel: LoginViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -28,6 +30,17 @@ class LoginActivity : AppCompatActivity() { } viewSet() + + binding.btnLogin.setOnClickListener { + val id = binding.etId.text.toString() + val pw = binding.etPw.text.toString() + viewModel.do_login(id, pw) + } + + binding.btnJoin.setOnClickListener { + //TODO Move 회원가입 + + } } private fun viewSet() { diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt new file mode 100644 index 0000000..b8dd82a --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt @@ -0,0 +1,10 @@ +package kr.ac.anu.mumu.presentation.login + +import androidx.lifecycle.ViewModel + +class LoginViewModel : ViewModel() { + + fun do_login(id: String, pw: String) { + + } +} \ No newline at end of file From 2a76aac4a642604ad74dc386d006df35a9800463 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 14:53:48 +0900 Subject: [PATCH 07/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20login=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI 마무리 --- .../main/res/drawable/btn_join_background.xml | 10 ++++++ app/src/main/res/drawable/gray_edit_box.xml | 3 +- app/src/main/res/layout/activity_login.xml | 31 ++++++++++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/btn_join_background.xml diff --git a/app/src/main/res/drawable/btn_join_background.xml b/app/src/main/res/drawable/btn_join_background.xml new file mode 100644 index 0000000..ab4e216 --- /dev/null +++ b/app/src/main/res/drawable/btn_join_background.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/gray_edit_box.xml b/app/src/main/res/drawable/gray_edit_box.xml index b9136e6..f7c1aec 100644 --- a/app/src/main/res/drawable/gray_edit_box.xml +++ b/app/src/main/res/drawable/gray_edit_box.xml @@ -1,5 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 8a406a0..8e59045 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -5,6 +5,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/white" tools:context=".presentation.login.LoginActivity"> + + + + \ No newline at end of file From e1b4b32bdab08a8d61cc48ae77b3e243710ee861 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 16:36:29 +0900 Subject: [PATCH 08/25] =?UTF-8?q?=E2=9C=85=20::=20gradle=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 22 +++++++++++++++++++ app/src/main/java/kr/ac/anu/mumu/di/.gitkeep | 0 .../java/kr/ac/anu/mumu/domain/model/.gitkeep | 0 .../kr/ac/anu/mumu/domain/repository/.gitkeep | 0 .../kr/ac/anu/mumu/domain/usecase/.gitkeep | 0 gradle/libs.versions.toml | 18 +++++++++++++++ 6 files changed, 40 insertions(+) delete mode 100644 app/src/main/java/kr/ac/anu/mumu/di/.gitkeep delete mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/model/.gitkeep delete mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/repository/.gitkeep delete mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/usecase/.gitkeep diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a681628..f048232 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,9 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) + id("kotlin-kapt") + id("com.google.dagger.hilt.android") version "2.48" + id("org.jlleitschuh.gradle.ktlint") version "11.6.1" } android { @@ -48,4 +51,23 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + + // Retrofit & GSON + implementation(libs.retrofit2) + implementation(libs.converter.gson) + + // Hilt + implementation(libs.hilt.android) + kapt(libs.hilt.android.compiler) + + // Coroutines + implementation(libs.kotlinx.coroutines.android) + + // ViewModel & LifeCycle + implementation(libs.androidx.lifecycle.viewmodel.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + + // UI 확장 + implementation(libs.androidx.activity.ktx) + implementation(libs.androidx.fragment.ktx) } \ No newline at end of file diff --git a/app/src/main/java/kr/ac/anu/mumu/di/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/model/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/repository/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b419512..0e7449e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,24 +1,42 @@ [versions] +activityKtx = "1.12.3" agp = "8.10.1" +fragmentKtx = "1.8.9" +hiltAndroid = "2.48" +hiltCompiler = "2.48" kotlin = "2.0.21" coreKtx = "1.17.0" junit = "4.13.2" junitVersion = "1.3.0" espressoCore = "3.7.0" appcompat = "1.7.1" +kotlinxCoroutinesAndroid = "1.9.0" +lifecycleViewmodelKtx = "2.10.0" material = "1.13.0" activity = "1.12.1" constraintlayout = "2.2.1" +retrofit2 = "2.9.0" [libraries] +androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleViewmodelKtx" } +androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } +converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit2" } +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } +hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } +hilt-compiler = { module = "com,google.dagger:hilt-compiler", version.ref = "hiltCompiler" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } +retrofit2 = { module = "com.squareup.retrofit2:retrofit2", version.ref = "retrofit2" } +hilt = { module = "com.google.dagger.hilt-android:2.48" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From 53b69ac31e76109ddcc0d39cc6528d05e551f193 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 16:36:39 +0900 Subject: [PATCH 09/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20data=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt | 6 ++++++ .../kr/ac/anu/mumu/domain/repository/LoginRepository.kt | 7 +++++++ .../java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt | 4 ++++ 3 files changed, 17 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt create mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt create mode 100644 app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt new file mode 100644 index 0000000..1e32aa7 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt @@ -0,0 +1,6 @@ +package kr.ac.anu.mumu.domain.model + +data class User( + val id: String, + val password: String, +) diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt new file mode 100644 index 0000000..253e44b --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt @@ -0,0 +1,7 @@ +package kr.ac.anu.mumu.domain.repository + +import kr.ac.anu.mumu.domain.model.User + +interface LoginRepository { + suspend fun login(id: String, pw: String) : Result +} \ No newline at end of file diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt new file mode 100644 index 0000000..740fd31 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt @@ -0,0 +1,4 @@ +package kr.ac.anu.mumu.domain.usecase + +class LoginUseCase @Inject constructor() { +} \ No newline at end of file From ce7b8d27623cf9799624f5a9fb503aa389ba99dd Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 16:43:35 +0900 Subject: [PATCH 10/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20UseCase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt index 740fd31..cf807f8 100644 --- a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt +++ b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt @@ -1,4 +1,13 @@ package kr.ac.anu.mumu.domain.usecase -class LoginUseCase @Inject constructor() { +import kr.ac.anu.mumu.domain.model.User +import kr.ac.anu.mumu.domain.repository.LoginRepository +import javax.inject.Inject + +class LoginUseCase @Inject constructor( + private val repository: LoginRepository +) { + suspend operator fun invoke(id: String, pw: String): Result { + return repository.login(id, pw) + } } \ No newline at end of file From 67fa8291b1a5c87bef2d7417247b8f484bb09cc5 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:51:23 +0900 Subject: [PATCH 11/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20user=20data=20c?= =?UTF-8?q?lass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt index 1e32aa7..8056a13 100644 --- a/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt +++ b/app/src/main/java/kr/ac/anu/mumu/domain/model/User.kt @@ -1,6 +1,8 @@ package kr.ac.anu.mumu.domain.model data class User( - val id: String, - val password: String, + val name: String, + val token: String, + val profileImage: String?, + val role: String ) From a573f3af50f964fac10e81271cd77b2efee6c7cd Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:53:45 +0900 Subject: [PATCH 12/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20AuthDto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/ac/anu/mumu/data/model/AuthDtos.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt new file mode 100644 index 0000000..92b4069 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt @@ -0,0 +1,28 @@ +package kr.ac.anu.mumu.data.model + +import com.google.gson.annotations.SerializedName + +data class LoginRequest( + @SerializedName("id") + val id: String, + @SerializedName("password") + val pw: String +) + +data class LoginResponse( + val success: Boolean, + val message: String, + val token: String, + val user: UserDto +) + +data class UserDto( + @SerializedName("user_id") + val userId: Int, + val id: String, + val name: String, + val phone: String?, + @SerializedName("profile_image") + val profileImage: String?, + val role: String +) \ No newline at end of file From 6199682275eec33226918fdb1bda6071eae9663e Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:55:12 +0900 Subject: [PATCH 13/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20AuthService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/ac/anu/mumu/data/datasource/.gitkeep | 0 .../kr/ac/anu/mumu/data/datasource/AuthService.kt | 12 ++++++++++++ 2 files changed, 12 insertions(+) delete mode 100644 app/src/main/java/kr/ac/anu/mumu/data/datasource/.gitkeep create mode 100644 app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/data/datasource/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/data/datasource/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt new file mode 100644 index 0000000..7c96437 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt @@ -0,0 +1,12 @@ +package kr.ac.anu.mumu.data.datasource + +import kr.ac.anu.mumu.data.model.LoginRequest +import kr.ac.anu.mumu.data.model.LoginResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.POST + +interface AuthService { + @POST("/api/users/login") + suspend fun login(@Body request: LoginRequest): Response +} \ No newline at end of file From 88468001bc8ea0928d37a6b13ac4138b2a86fc17 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:56:00 +0900 Subject: [PATCH 14/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20LoginRepository?= =?UTF-8?q?Impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LoginRepository 상속 받아 실제 통신 코드 작성 --- .../kr/ac/anu/mumu/data/repository/.gitkeep | 0 .../data/repository/LoginRepositoryImpl.kt | 38 +++++++++++++++++++ 2 files changed, 38 insertions(+) delete mode 100644 app/src/main/java/kr/ac/anu/mumu/data/repository/.gitkeep create mode 100644 app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/data/repository/.gitkeep b/app/src/main/java/kr/ac/anu/mumu/data/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt new file mode 100644 index 0000000..f8c2023 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt @@ -0,0 +1,38 @@ +package kr.ac.anu.mumu.data.repository + +import kr.ac.anu.mumu.data.datasource.AuthService +import kr.ac.anu.mumu.data.model.LoginRequest +import kr.ac.anu.mumu.domain.model.User +import kr.ac.anu.mumu.domain.repository.LoginRepository +import javax.inject.Inject + +class LoginRepositoryImpl @Inject constructor( + private val authService: AuthService +) : LoginRepository { + + override suspend fun login(id: String, pw: String): Result { + return try { + val response = authService.login(LoginRequest(id, pw)) + + if (response.isSuccessful && response.body() != null) { + val result = response.body()!! + + if (result.success) { + val domainUser = User( + name = result.user.name, + token = result.token, + profileImage = result.user.profileImage, + role = result.user.role + ) + Result.success(domainUser) + } else { + Result.failure(Exception(result.message)) + } + } else { + Result.failure(Exception("통신 오류 : ${response.code()}")) + } + } catch (e: Exception) { + Result.failure(e) + } + } +} \ No newline at end of file From b241b9eae8b3cc02952c863c1484d95f17adfe75 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:56:30 +0900 Subject: [PATCH 15/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20NetworkModule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retrofit 객체 생성 방법 등록 -> 서버 주소 임시 제외 --- .../java/kr/ac/anu/mumu/di/NetworkModule.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt new file mode 100644 index 0000000..3078f71 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt @@ -0,0 +1,29 @@ +package kr.ac.anu.mumu.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kr.ac.anu.mumu.data.datasource.AuthService +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object NetworkModule { + @Provides + @Singleton + fun provideRetrofit(): Retrofit { + return Retrofit.Builder() + .baseUrl("") //서버 주소 + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + + @Provides + @Singleton + fun provideAuthService(retrofit: Retrofit): AuthService { + return retrofit.create(AuthService::class.java) + } +} \ No newline at end of file From 162e8a8fcb2ba808499c3f1efff66e20da7b34cb Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:56:48 +0900 Subject: [PATCH 16/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20RepositoryModul?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 인터페이스와 구현체 연결 --- .../kr/ac/anu/mumu/di/RepositoryModule.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt diff --git a/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt new file mode 100644 index 0000000..3e12006 --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/di/RepositoryModule.kt @@ -0,0 +1,19 @@ +package kr.ac.anu.mumu.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kr.ac.anu.mumu.data.repository.LoginRepositoryImpl +import kr.ac.anu.mumu.domain.repository.LoginRepository +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class RepositoryModule { + @Binds + @Singleton + abstract fun bindLoginRepository( + loginRepositoryImpl: LoginRepositoryImpl + ): LoginRepository +} From 1b04ef6927817f4076a76f1a9600a24058ff4e4c Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 19:57:03 +0900 Subject: [PATCH 17/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20Hilt=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 7 ++++--- app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4d54553..8a57fa5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> + android:exported="true"> @@ -23,8 +24,8 @@ - + android:exported="false" /> + \ No newline at end of file diff --git a/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt new file mode 100644 index 0000000..8f0806f --- /dev/null +++ b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt @@ -0,0 +1,7 @@ +package kr.ac.anu.mumu + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp + +@HiltAndroidApp +class MumuApplication : Application() \ No newline at end of file From ce4665e7c74c5107da871d599bc14e4a476d417a Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 21:11:23 +0900 Subject: [PATCH 18/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20LoginViewModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mumu/presentation/login/LoginViewModel.kt | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt index b8dd82a..3e77534 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt @@ -1,10 +1,44 @@ package kr.ac.anu.mumu.presentation.login import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import kr.ac.anu.mumu.domain.usecase.LoginUseCase +import javax.inject.Inject -class LoginViewModel : ViewModel() { +@HiltViewModel +class LoginViewModel @Inject constructor( + private val loginUseCase: LoginUseCase +) : ViewModel() { - fun do_login(id: String, pw: String) { + // 화면 상태 + sealed class UiState { + object Idle : UiState() // 대기 + object Loading : UiState() // 로딩 + object Success : UiState() // 로그인 성공 + data class Error(val message: String) : UiState() // 실패 + } + + private val _loginState = MutableStateFlow(UiState.Idle) + val loginState: StateFlow = _loginState.asStateFlow() + + // 로그인 함수 + fun login(id: String, pw: String) { + viewModelScope.launch { + _loginState.value = UiState.Loading + + loginUseCase(id, pw) + .onSuccess { + _loginState.value = UiState.Success + } + .onFailure { error -> + _loginState.value = UiState.Error(error.message ?: "로그인 실패") + } + } } } \ No newline at end of file From 5370c8ec9dad28c49f299d75cd9a63c8c6fb6505 Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 21:21:39 +0900 Subject: [PATCH 19/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20login=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚡️ :: separate sealed class --- .../mumu/presentation/login/LoginActivity.kt | 77 ++++++++++++++++--- .../mumu/presentation/login/LoginViewModel.kt | 26 +++---- app/src/main/res/layout/activity_login.xml | 12 +++ 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt index 287271e..1161b7a 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -1,17 +1,26 @@ package kr.ac.anu.mumu.presentation.login +import android.content.Intent import android.os.Bundle +import android.text.Editable import android.text.Spannable import android.text.SpannableStringBuilder +import android.text.TextWatcher import android.text.style.ForegroundColorSpan +import android.view.View import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.launch import kr.ac.anu.mumu.R import kr.ac.anu.mumu.databinding.ActivityLoginBinding +import kr.ac.anu.mumu.presentation.main.MainActivity class LoginActivity : AppCompatActivity() { @@ -31,16 +40,8 @@ class LoginActivity : AppCompatActivity() { viewSet() - binding.btnLogin.setOnClickListener { - val id = binding.etId.text.toString() - val pw = binding.etPw.text.toString() - viewModel.do_login(id, pw) - } - - binding.btnJoin.setOnClickListener { - //TODO Move 회원가입 - - } + initInputListener() + initObserver() } private fun viewSet() { @@ -64,4 +65,60 @@ class LoginActivity : AppCompatActivity() { binding.tvTitle.text = spannable } + + private fun initInputListener() { + val textWatcher = object : TextWatcher { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + override fun afterTextChanged(p0: Editable?) { + val id = binding.etId.text.toString() + val pw = binding.etPw.text.toString() + + binding.btnLogin.isEnabled = id.isNotEmpty() && pw.isNotEmpty() + + binding.tvError.visibility = View.GONE + } + } + + binding.etId.addTextChangedListener(textWatcher) + binding.etPw.addTextChangedListener(textWatcher) + + // 버튼 클릭 시 로그인 요청 + binding.btnLogin.setOnClickListener { + val id = binding.etId.text.toString() + val pw = binding.etPw.text.toString() + + viewModel.login(id, pw) + } + } + + // 로그인 결과 -> UI 업데이트 + private fun initObserver() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.uiState.collect { state -> + when (state) { + is LoginUiState.Loading -> { + // 로딩 상태 처리 + binding.btnLogin.isEnabled = false + } + is LoginUiState.Success -> { + // 로그인 성공 처리 + val intent = Intent(this@LoginActivity, MainActivity::class.java) + startActivity(intent) + finish() + } + is LoginUiState.Error -> { + // 로그인 실패 처리 + binding.tvError.visibility = View.VISIBLE + binding.tvError.text = state.message + binding.btnLogin.isEnabled = true + } + else -> {} + } + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt index 3e77534..ef334ed 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt @@ -11,32 +11,32 @@ import kr.ac.anu.mumu.domain.usecase.LoginUseCase import javax.inject.Inject @HiltViewModel +// 화면 상태 +sealed class LoginUiState { + object Idle : LoginUiState() // 대기 + object Loading : LoginUiState() // 로딩 + object Success : LoginUiState() // 로그인 성공 + data class Error(val message: String) : LoginUiState() // 실패 +} + class LoginViewModel @Inject constructor( private val loginUseCase: LoginUseCase ) : ViewModel() { - // 화면 상태 - sealed class UiState { - object Idle : UiState() // 대기 - object Loading : UiState() // 로딩 - object Success : UiState() // 로그인 성공 - data class Error(val message: String) : UiState() // 실패 - } - - private val _loginState = MutableStateFlow(UiState.Idle) - val loginState: StateFlow = _loginState.asStateFlow() + private val _uiState = MutableStateFlow(LoginUiState.Idle) + val uiState: StateFlow = _uiState.asStateFlow() // 로그인 함수 fun login(id: String, pw: String) { viewModelScope.launch { - _loginState.value = UiState.Loading + _uiState.value = LoginUiState.Loading loginUseCase(id, pw) .onSuccess { - _loginState.value = UiState.Success + _uiState.value = LoginUiState.Success } .onFailure { error -> - _loginState.value = UiState.Error(error.message ?: "로그인 실패") + _uiState.value = LoginUiState.Error(error.message ?: "로그인 실패") } } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 8e59045..0c52a7a 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -54,6 +54,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/et_id" /> + + Date: Tue, 10 Feb 2026 22:25:22 +0900 Subject: [PATCH 20/25] =?UTF-8?q?=F0=9F=90=9B=20::=20jetpack=20version=20m?= =?UTF-8?q?odify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 :: HiltViewModel position modify --- .../java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt | 2 +- gradle/libs.versions.toml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt index ef334ed..76960b1 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt @@ -10,7 +10,6 @@ import kotlinx.coroutines.launch import kr.ac.anu.mumu.domain.usecase.LoginUseCase import javax.inject.Inject -@HiltViewModel // 화면 상태 sealed class LoginUiState { object Idle : LoginUiState() // 대기 @@ -19,6 +18,7 @@ sealed class LoginUiState { data class Error(val message: String) : LoginUiState() // 실패 } +@HiltViewModel class LoginViewModel @Inject constructor( private val loginUseCase: LoginUseCase ) : ViewModel() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0e7449e..6be4f55 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,6 @@ activityKtx = "1.12.3" agp = "8.10.1" fragmentKtx = "1.8.9" hiltAndroid = "2.48" -hiltCompiler = "2.48" kotlin = "2.0.21" coreKtx = "1.17.0" junit = "4.13.2" @@ -26,7 +25,6 @@ androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-view converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit2" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } -hilt-compiler = { module = "com,google.dagger:hilt-compiler", version.ref = "hiltCompiler" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -35,8 +33,7 @@ kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutine material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } -retrofit2 = { module = "com.squareup.retrofit2:retrofit2", version.ref = "retrofit2" } -hilt = { module = "com.google.dagger.hilt-android:2.48" } +retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit2" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From b73915ea8ca1223c5a7e6f09f771fc51e99d5b3c Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 23:05:07 +0900 Subject: [PATCH 21/25] =?UTF-8?q?=F0=9F=90=9B=20::=20Hilt=20bug=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- app/src/main/AndroidManifest.xml | 2 ++ .../java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt | 2 ++ build.gradle.kts | 1 + gradle/libs.versions.toml | 4 ++-- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f048232..9b85d7c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,7 +2,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) id("kotlin-kapt") - id("com.google.dagger.hilt.android") version "2.48" + alias(libs.plugins.hilt.android) id("org.jlleitschuh.gradle.ktlint") version "11.6.1" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8a57fa5..b8a521c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + Date: Tue, 10 Feb 2026 23:05:54 +0900 Subject: [PATCH 22/25] =?UTF-8?q?=F0=9F=90=9B=20::=20temporary=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt index 3078f71..deff2d6 100644 --- a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt +++ b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt @@ -16,7 +16,7 @@ object NetworkModule { @Singleton fun provideRetrofit(): Retrofit { return Retrofit.Builder() - .baseUrl("") //서버 주소 + .baseUrl("http://localhost/") //서버 주소 .addConverterFactory(GsonConverterFactory.create()) .build() } From 73a287e602235c17d88fce7dcc358b31aea1238e Mon Sep 17 00:00:00 2001 From: bhindor Date: Tue, 10 Feb 2026 23:14:32 +0900 Subject: [PATCH 23/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20error=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt index 499e71e..692eb83 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -7,6 +7,7 @@ import android.text.Spannable import android.text.SpannableStringBuilder import android.text.TextWatcher import android.text.style.ForegroundColorSpan +import android.util.Log import android.view.View import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels @@ -114,7 +115,7 @@ class LoginActivity : AppCompatActivity() { is LoginUiState.Error -> { // 로그인 실패 처리 binding.tvError.visibility = View.VISIBLE - binding.tvError.text = state.message + Log.e("에러 로그 : ", state.message) binding.btnLogin.isEnabled = true } else -> {} From 8eb1db13a84cc7115a94ac4adfed93784ddd1873 Mon Sep 17 00:00:00 2001 From: bhindor Date: Wed, 11 Feb 2026 20:52:31 +0900 Subject: [PATCH 24/25] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20login=20api=20m?= =?UTF-8?q?odify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt | 2 +- .../java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b8a521c..f0aaafd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ { // 로그인 실패 처리 binding.tvError.visibility = View.VISIBLE - Log.e("에러 로그 : ", state.message) + Log.e("emumu : ", state.message) binding.btnLogin.isEnabled = true } else -> {} From 06e8838142faa23910e3495cebdd3fb153f21d74 Mon Sep 17 00:00:00 2001 From: bhindor Date: Wed, 11 Feb 2026 21:03:23 +0900 Subject: [PATCH 25/25] =?UTF-8?q?=F0=9F=8E=A8=20::=20ktlint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- .../java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt | 8 +++----- app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt | 2 +- .../java/kr/ac/anu/mumu/data/datasource/AuthService.kt | 2 +- app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt | 2 +- .../kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt | 2 +- app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt | 4 ++-- .../kr/ac/anu/mumu/domain/repository/LoginRepository.kt | 4 ++-- .../java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt | 2 +- .../kr/ac/anu/mumu/presentation/login/LoginActivity.kt | 4 ++-- .../kr/ac/anu/mumu/presentation/login/LoginViewModel.kt | 3 +-- .../java/kr/ac/anu/mumu/presentation/main/MainActivity.kt | 2 +- app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt | 5 ++--- 13 files changed, 19 insertions(+), 23 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9b85d7c..eecd9ed 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -70,4 +70,4 @@ dependencies { // UI 확장 implementation(libs.androidx.activity.ktx) implementation(libs.androidx.fragment.ktx) -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt b/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt index 6ba8b6f..2857e90 100644 --- a/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/kr/ac/anu/mumu/ExampleInstrumentedTest.kt @@ -1,13 +1,11 @@ package kr.ac.anu.mumu -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 - +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith -import org.junit.Assert.* - /** * Instrumented test, which will execute on an Android device. * @@ -21,4 +19,4 @@ class ExampleInstrumentedTest { val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("kr.ac.anu.mumu", appContext.packageName) } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt index 8f0806f..5eceb62 100644 --- a/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt +++ b/app/src/main/java/kr/ac/anu/mumu/MumuApplication.kt @@ -4,4 +4,4 @@ import android.app.Application import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class MumuApplication : Application() \ No newline at end of file +class MumuApplication : Application() diff --git a/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt index 7c96437..8c3d418 100644 --- a/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt +++ b/app/src/main/java/kr/ac/anu/mumu/data/datasource/AuthService.kt @@ -9,4 +9,4 @@ import retrofit2.http.POST interface AuthService { @POST("/api/users/login") suspend fun login(@Body request: LoginRequest): Response -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt index 92b4069..01e8b01 100644 --- a/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt +++ b/app/src/main/java/kr/ac/anu/mumu/data/model/AuthDtos.kt @@ -25,4 +25,4 @@ data class UserDto( @SerializedName("profile_image") val profileImage: String?, val role: String -) \ No newline at end of file +) diff --git a/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt index f8c2023..27749cc 100644 --- a/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt +++ b/app/src/main/java/kr/ac/anu/mumu/data/repository/LoginRepositoryImpl.kt @@ -35,4 +35,4 @@ class LoginRepositoryImpl @Inject constructor( Result.failure(e) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt index 3782a22..f0cdb98 100644 --- a/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt +++ b/app/src/main/java/kr/ac/anu/mumu/di/NetworkModule.kt @@ -16,7 +16,7 @@ object NetworkModule { @Singleton fun provideRetrofit(): Retrofit { return Retrofit.Builder() - .baseUrl("https://keagan-slipperier-bewilderedly.ngrok-free.dev") //서버 주소 + .baseUrl("https://keagan-slipperier-bewilderedly.ngrok-free.dev") // 서버 주소 .addConverterFactory(GsonConverterFactory.create()) .build() } @@ -26,4 +26,4 @@ object NetworkModule { fun provideAuthService(retrofit: Retrofit): AuthService { return retrofit.create(AuthService::class.java) } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt index 253e44b..de31e19 100644 --- a/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt +++ b/app/src/main/java/kr/ac/anu/mumu/domain/repository/LoginRepository.kt @@ -3,5 +3,5 @@ package kr.ac.anu.mumu.domain.repository import kr.ac.anu.mumu.domain.model.User interface LoginRepository { - suspend fun login(id: String, pw: String) : Result -} \ No newline at end of file + suspend fun login(id: String, pw: String): Result +} diff --git a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt index cf807f8..051a3d6 100644 --- a/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt +++ b/app/src/main/java/kr/ac/anu/mumu/domain/usecase/LoginUseCase.kt @@ -10,4 +10,4 @@ class LoginUseCase @Inject constructor( suspend operator fun invoke(id: String, pw: String): Result { return repository.login(id, pw) } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt index cd5f60e..5856b43 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginActivity.kt @@ -33,7 +33,7 @@ class LoginActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - binding = ActivityLoginBinding.inflate(layoutInflater) + binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) @@ -124,4 +124,4 @@ class LoginActivity : AppCompatActivity() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt index 76960b1..6bc6345 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/login/LoginViewModel.kt @@ -38,7 +38,6 @@ class LoginViewModel @Inject constructor( .onFailure { error -> _uiState.value = LoginUiState.Error(error.message ?: "로그인 실패") } - } } -} \ No newline at end of file +} diff --git a/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt b/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt index 93bdd86..7901e6c 100644 --- a/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt +++ b/app/src/main/java/kr/ac/anu/mumu/presentation/main/MainActivity.kt @@ -18,4 +18,4 @@ class MainActivity : AppCompatActivity() { insets } } -} \ No newline at end of file +} diff --git a/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt b/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt index 11aca07..fce10fb 100644 --- a/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt +++ b/app/src/test/java/kr/ac/anu/mumu/ExampleUnitTest.kt @@ -1,9 +1,8 @@ package kr.ac.anu.mumu +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert.* - /** * Example local unit test, which will execute on the development machine (host). * @@ -14,4 +13,4 @@ class ExampleUnitTest { fun addition_isCorrect() { assertEquals(4, 2 + 2) } -} \ No newline at end of file +}