diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 051ddb6..0000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 5e0fb6b..e2dca59 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -11,7 +11,9 @@
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 82f1c99..92351c6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -16,7 +16,6 @@ android {
targetSdk 33
versionCode 1
versionName "1.0"
-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -40,7 +39,7 @@ android {
dependencies {
- api project(path: ':common-ui')
+
api project(path: ':story')
api project(path: ':home')
api project(path: ':setting')
@@ -50,8 +49,7 @@ dependencies {
// Hilt
implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
- kaptAndroidTest "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
- androidTestImplementation "com.google.dagger:hilt-android-testing:$rootProject.hiltVersion"
+
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.0'
@@ -60,4 +58,8 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
+
+kapt {
+ correctErrorTypes true
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1253878..8b07682 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
+
+
-
-
-
-
+ android:exported="false">
+
diff --git a/app/src/main/java/com/najudoryeong/mineme/MainActivity.kt b/app/src/main/java/com/najudoryeong/mineme/MainActivity.kt
index 35a6043..1eab185 100644
--- a/app/src/main/java/com/najudoryeong/mineme/MainActivity.kt
+++ b/app/src/main/java/com/najudoryeong/mineme/MainActivity.kt
@@ -3,6 +3,7 @@ package com.najudoryeong.mineme
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
+import android.view.WindowManager
import androidx.activity.viewModels
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
@@ -14,9 +15,11 @@ import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import com.najudoryeong.mineme.common_ui.MainActivityUtil
import com.najudoryeong.mineme.databinding.ActivityMainBinding
+import dagger.hilt.android.AndroidEntryPoint
// 하위 모듈이 MainViewModel 코드에 접근할 수 있게 MainViewModelUtil 상속 구현
+@AndroidEntryPoint
class MainActivity : AppCompatActivity(), MainActivityUtil {
private lateinit var binding: ActivityMainBinding
@@ -30,29 +33,10 @@ class MainActivity : AppCompatActivity(), MainActivityUtil {
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.viewModel = model
+
initAppBar()
initBottomNav()
- setStartDestination(isLogin())
-
- }
-
-
- /**
- * login 여부에 따른 startDestination 조작을 위해
- * main graph를 가져와서 startDestination을 조작 후 변경내용을 적용한다.
- * */
-
- private fun setStartDestination(isLogin: Boolean) {
- val navGraph = navController.navInflater.inflate(R.navigation.nav_main)
- if (isLogin) navGraph.setStartDestination(R.id.nav_home)
- else navGraph.setStartDestination(com.najudoryeong.mineme.onboarding.R.id.nav_onboarding)
- navController.setGraph(navGraph, null)
- }
-
- // todo 로그인 체크 로직
- private fun isLogin(): Boolean {
- return true
}
private fun initBottomNav() {
@@ -89,15 +73,14 @@ class MainActivity : AppCompatActivity(), MainActivityUtil {
binding.topAppBar.visibility = View.VISIBLE
}
+
+
+
/** [MainActivityUtil] */
override fun setToolbarTitle(newTitle: String) {
binding.toolbar.title = newTitle
}
- override fun navigateToHome(start: Fragment) {
- start.findNavController().navigate(R.id.nav_home)
- showAppBar()
- }
override fun setVisibilityBottomAppbar(visibilityMode: Int) {
binding.bottomAppBar.visibility = visibilityMode
diff --git a/app/src/main/java/com/najudoryeong/mineme/MineMeApplication.kt b/app/src/main/java/com/najudoryeong/mineme/MineMeApplication.kt
index c1e45a6..5502347 100644
--- a/app/src/main/java/com/najudoryeong/mineme/MineMeApplication.kt
+++ b/app/src/main/java/com/najudoryeong/mineme/MineMeApplication.kt
@@ -1,9 +1,22 @@
package com.najudoryeong.mineme
import android.app.Application
+import android.util.Log
+import com.example.common.util.NATIVE_APP_KEY
+import com.kakao.sdk.common.KakaoSdk
+import com.kakao.sdk.common.util.Utility
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MineMeApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ KakaoSdk.init(this, NATIVE_APP_KEY)
+ //printAppKeyHash()
+ }
+ private fun printAppKeyHash() {
+ val keyHash = Utility.getKeyHash(this)
+ Log.d("KeyHash", keyHash)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index af794ed..972d88e 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -22,6 +22,7 @@
android:orientation="vertical">
diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml
index a777d12..ea35da8 100644
--- a/app/src/main/res/navigation/nav_main.xml
+++ b/app/src/main/res/navigation/nav_main.xml
@@ -4,7 +4,6 @@
android:id="@+id/nav_graph"
app:startDestination="@id/nav_home">
-
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 90626fd..4cb7216 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,6 +1,9 @@
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 8bdc3e4..d4a77ef 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,12 +5,19 @@ buildscript {
google()
gradlePluginPortal()
mavenCentral()
+ maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/'}
}
ext {
hiltVersion = '2.44'
nav_version = '2.5.3'
fragment_version = "1.5.5"
+ okHttpVersion = '4.10.0'
+ hiltVersion = '2.44'
+ kakao_version = '2.12.1'
+ dataStorePreferences_version = '1.0.0'
+ retrofit2Version = '2.9.0'
+
}
dependencies {
@@ -20,6 +27,7 @@ buildscript {
}
plugins {
+ id 'com.google.dagger.hilt.android' version '2.44' apply false
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
diff --git a/common-ui/build.gradle b/common-ui/build.gradle
index a204714..bd1fcd6 100644
--- a/common-ui/build.gradle
+++ b/common-ui/build.gradle
@@ -2,6 +2,8 @@ plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'androidx.navigation.safeargs.kotlin'
+ id 'kotlin-kapt'
+ id 'com.google.dagger.hilt.android'
}
android {
@@ -50,6 +52,17 @@ dependencies {
api "androidx.fragment:fragment:$rootProject.fragment_version"
api "androidx.fragment:fragment-ktx:$rootProject.fragment_version"
+
+ // Hilt
+ implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
+ kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
+
+
+ // Glide
+ implementation 'com.github.bumptech.glide:glide:4.14.2'
+ kapt 'com.github.bumptech.glide:compiler:4.14.2'
+
+
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.8.0'
diff --git a/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/BindingAdapter.kt b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/BindingAdapter.kt
new file mode 100644
index 0000000..a1c0ead
--- /dev/null
+++ b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/BindingAdapter.kt
@@ -0,0 +1,15 @@
+package com.najudoryeong.mineme.common_ui
+
+import android.widget.ImageView
+import androidx.databinding.BindingAdapter
+import com.bumptech.glide.Glide
+
+
+@BindingAdapter("photoUrl")
+fun bindImageView(imageView: ImageView, photoUrl: String?) {
+ Glide.with(imageView.context)
+ .load(photoUrl)
+ .placeholder(R.drawable.img_profile)
+ .into(imageView)
+}
+
diff --git a/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/DialogForPermission.kt b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/DialogForPermission.kt
new file mode 100644
index 0000000..94717cc
--- /dev/null
+++ b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/DialogForPermission.kt
@@ -0,0 +1,59 @@
+package com.najudoryeong.mineme.common_ui
+
+import android.app.Dialog
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import com.najudoryeong.mineme.common_ui.databinding.DialogForPermissionBinding
+
+class DialogForPermission(
+ context: Context,
+ private val message: String,
+ private val imgId: Int,
+ private val onClickButton: () -> Unit
+) : Dialog(context){
+
+ private lateinit var binding: DialogForPermissionBinding
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = DialogForPermissionBinding.inflate(layoutInflater).apply {
+ dialogTv.text = message
+ dialogIv.setImageResource(imgId)
+ dialogButton.setOnClickListener {
+ onClickButton.invoke()
+ dismiss()
+ }
+ }
+ setContentView(binding.root)
+
+ window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ }
+
+ class Builder(private val context: Context) {
+ private var message = ""
+ private var imgId = 0
+ private var onClickButton = {}
+
+ fun setMessage(message: String) = apply {
+ this.message = message
+ }
+
+ fun setImg(imgId: Int) = apply {
+ this.imgId = imgId
+ }
+
+ fun setOnClickButton(onClickButton: () -> Unit) = apply {
+ this.onClickButton = onClickButton
+ }
+
+ fun build() = DialogForPermission(
+ context,
+ message,
+ imgId,
+ onClickButton
+ )
+ }
+}
\ No newline at end of file
diff --git a/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/MainActivityUtil.kt b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/MainActivityUtil.kt
index 26b4f5e..18613b8 100644
--- a/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/MainActivityUtil.kt
+++ b/common-ui/src/main/java/com/najudoryeong/mineme/common_ui/MainActivityUtil.kt
@@ -4,7 +4,6 @@ import androidx.fragment.app.Fragment
interface MainActivityUtil{
fun setToolbarTitle(newTitle: String)
- fun navigateToHome(start : Fragment)
fun setVisibilityBottomAppbar(visibilityMode : Int)
fun setVisibilityTopAppBar(visibilityMode: Int)
}
\ No newline at end of file
diff --git a/common-ui/src/main/res/drawable/img_profile.xml b/common-ui/src/main/res/drawable/img_profile.xml
new file mode 100644
index 0000000..3569254
--- /dev/null
+++ b/common-ui/src/main/res/drawable/img_profile.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common-ui/src/main/res/layout/dialog_for_permission.xml b/common-ui/src/main/res/layout/dialog_for_permission.xml
new file mode 100644
index 0000000..346d6f4
--- /dev/null
+++ b/common-ui/src/main/res/layout/dialog_for_permission.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common-ui/src/main/res/layout/item_story.xml b/common-ui/src/main/res/layout/item_story.xml
new file mode 100644
index 0000000..b9fb288
--- /dev/null
+++ b/common-ui/src/main/res/layout/item_story.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common-ui/src/main/res/values/dimens.xml b/common-ui/src/main/res/values/dimens.xml
index 26c64d7..d4c983c 100644
--- a/common-ui/src/main/res/values/dimens.xml
+++ b/common-ui/src/main/res/values/dimens.xml
@@ -2,4 +2,7 @@
21dp
21dp
+ 17dp
+ 4sp
+ 17sp
\ No newline at end of file
diff --git a/common-ui/src/main/res/values/strings.xml b/common-ui/src/main/res/values/strings.xml
index 5cd1889..07d090c 100644
--- a/common-ui/src/main/res/values/strings.xml
+++ b/common-ui/src/main/res/values/strings.xml
@@ -1,6 +1,8 @@
- Hello blank fragment
+ mineme
다음
확인
+ New Story
+ No Story
\ No newline at end of file
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 0000000..33da4fd
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,56 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+ id 'kotlin-kapt'
+ id 'com.google.dagger.hilt.android'
+ id 'androidx.navigation.safeargs.kotlin'
+
+}
+
+android {
+ namespace 'com.example.common'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 23
+ targetSdk 33
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ api project(path: ':foundation')
+
+ // Preferences DataStore
+ implementation("androidx.datastore:datastore-preferences:$rootProject.dataStorePreferences_version")
+
+ api "com.kakao.sdk:v2-all:$rootProject.kakao_version"
+
+ // Hilt
+ implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
+ kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
+
+ implementation 'androidx.core:core-ktx:1.9.0'
+ implementation 'androidx.appcompat:appcompat:1.6.0'
+ implementation 'com.google.android.material:material:1.8.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
\ No newline at end of file
diff --git a/common/consumer-rules.pro b/common/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/common/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/common/src/androidTest/java/com/example/common/ExampleInstrumentedTest.kt b/common/src/androidTest/java/com/example/common/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..0886bf6
--- /dev/null
+++ b/common/src/androidTest/java/com/example/common/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.common
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.common.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e6aae30
--- /dev/null
+++ b/common/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/CodeRequest.kt b/common/src/main/java/com/example/common/data/dto/CodeRequest.kt
new file mode 100644
index 0000000..557aeeb
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/CodeRequest.kt
@@ -0,0 +1,5 @@
+package com.example.common.data.dto
+
+data class CodeRequest(
+ val code : String
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/HomeResponse.kt b/common/src/main/java/com/example/common/data/dto/HomeResponse.kt
new file mode 100644
index 0000000..a918119
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/HomeResponse.kt
@@ -0,0 +1,8 @@
+package com.example.common.data.dto
+
+import com.example.common.data.entity.HomeData
+
+data class HomeResponse(
+ val data: HomeData,
+ val success: Boolean
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/LoginRequest.kt b/common/src/main/java/com/example/common/data/dto/LoginRequest.kt
new file mode 100644
index 0000000..177ab77
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/LoginRequest.kt
@@ -0,0 +1,7 @@
+package com.example.common.data.dto
+
+data class LoginRequest(
+ val accessToken: String,
+ val providerType: String,
+ val userName: String
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/LoginResponse.kt b/common/src/main/java/com/example/common/data/dto/LoginResponse.kt
new file mode 100644
index 0000000..249dc22
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/LoginResponse.kt
@@ -0,0 +1,8 @@
+package com.example.common.data.dto
+
+import com.example.common.data.entity.LoginData
+
+data class LoginResponse(
+ val success: Boolean,
+ val data: LoginData
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/NullResponse.kt b/common/src/main/java/com/example/common/data/dto/NullResponse.kt
new file mode 100644
index 0000000..7ea3135
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/NullResponse.kt
@@ -0,0 +1,6 @@
+package com.example.common.data.dto
+
+data class NullResponse(
+ val success: Boolean,
+ val data: String?
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/dto/UserInfoRequest.kt b/common/src/main/java/com/example/common/data/dto/UserInfoRequest.kt
new file mode 100644
index 0000000..4ac4985
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/dto/UserInfoRequest.kt
@@ -0,0 +1,6 @@
+package com.example.common.data.dto
+
+data class UserInfoRequest(
+ val nickname: String,
+ val birthday: String
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/entity/HomeData.kt b/common/src/main/java/com/example/common/data/entity/HomeData.kt
new file mode 100644
index 0000000..49b7b56
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/entity/HomeData.kt
@@ -0,0 +1,57 @@
+package com.example.common.data.entity
+
+data class HomeData(
+ val couple: Couple,
+ val newStory: NewStory,
+ val widgets: List
+)
+
+
+data class Couple(
+ val me: Me,
+ val mine: Mine,
+ val name: String,
+ val startDate: String
+)
+
+
+data class NewStory(
+ val date: String,
+ val postId: Int,
+ val region: String,
+ val thumbnailImage: String
+)
+
+
+data class Mine(
+ val birthday: String,
+ val description: String,
+ val gender: String,
+ val instaId: String,
+ val nickname: String,
+ val profileImage: String
+)
+
+
+data class Me(
+ val birthday: String,
+ val description: String,
+ val gender: String,
+ val instaId: String,
+ val nickname: String,
+ val profileImage: String
+)
+
+
+data class Widget(
+ val Id: Int,
+ val color: String,
+ val heigth: Int,
+ val name: String,
+ val order: Int,
+ val type: String,
+ val widget: WidgetX,
+ val width: Int
+)
+
+class WidgetX
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/entity/LoginData.kt b/common/src/main/java/com/example/common/data/entity/LoginData.kt
new file mode 100644
index 0000000..22420d5
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/entity/LoginData.kt
@@ -0,0 +1,6 @@
+package com.example.common.data.entity
+
+data class LoginData(
+ val jwt: String,
+ val code: String
+)
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/entity/ProviderName.kt b/common/src/main/java/com/example/common/data/entity/ProviderName.kt
new file mode 100644
index 0000000..89a9288
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/entity/ProviderName.kt
@@ -0,0 +1,5 @@
+package com.example.common.data.entity
+
+enum class ProviderType(providerType: String) {
+ KAKAO("KAKAO")
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/source/AuthService.kt b/common/src/main/java/com/example/common/data/source/AuthService.kt
new file mode 100644
index 0000000..55a82c3
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/source/AuthService.kt
@@ -0,0 +1,11 @@
+package com.example.common.data.source
+
+import com.example.common.data.dto.LoginRequest
+import com.example.common.data.dto.LoginResponse
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface AuthService {
+ @POST("api/v1/oauth/login")
+ suspend fun login(@Body loginRequest: LoginRequest): LoginResponse
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/data/source/UserService.kt b/common/src/main/java/com/example/common/data/source/UserService.kt
new file mode 100644
index 0000000..9176de6
--- /dev/null
+++ b/common/src/main/java/com/example/common/data/source/UserService.kt
@@ -0,0 +1,34 @@
+package com.example.common.data.source
+
+import com.example.common.data.dto.CodeRequest
+import com.example.common.data.dto.HomeResponse
+import com.example.common.data.dto.UserInfoRequest
+import com.example.common.data.dto.NullResponse
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.Header
+import retrofit2.http.POST
+
+interface UserService {
+
+ @POST("api/v1/user/info")
+ suspend fun postUserInfo(
+ @Header("Authorization") token: String,
+ @Body userInfoRequest: UserInfoRequest
+ ): NullResponse
+
+
+ @POST("api/v1/user/code")
+ suspend fun postTargetCode(
+ @Header("Authorization") token: String,
+ @Body userCodeRequest: CodeRequest
+ ): NullResponse
+
+
+ @GET("api/test/main/info")
+ suspend fun getHomeInfo(
+ @Header("Authorization") token: String,
+ ): HomeResponse
+
+
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/di/DataStoreModule.kt b/common/src/main/java/com/example/common/di/DataStoreModule.kt
new file mode 100644
index 0000000..0063ed8
--- /dev/null
+++ b/common/src/main/java/com/example/common/di/DataStoreModule.kt
@@ -0,0 +1,30 @@
+package com.example.common.di
+
+import android.content.Context
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.preferencesDataStore
+import com.example.common.domain.usecase.DataStoreUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@InstallIn(SingletonComponent::class)
+@Module
+class DataStoreModule {
+
+ private val Context.dataStore: DataStore by preferencesDataStore(
+ name = DataStoreUseCase.DATA_STORE_NAME
+ )
+
+
+
+ @Singleton
+ @Provides
+ fun providePreferencesDataStore(@ApplicationContext context: Context) =
+ DataStoreUseCase(context.dataStore)
+
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/di/NetworkModule.kt b/common/src/main/java/com/example/common/di/NetworkModule.kt
new file mode 100644
index 0000000..c8a30f6
--- /dev/null
+++ b/common/src/main/java/com/example/common/di/NetworkModule.kt
@@ -0,0 +1,29 @@
+package com.example.common.di
+
+import com.example.common.data.source.AuthService
+import com.example.common.data.source.UserService
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import retrofit2.Retrofit
+import retrofit2.create
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class NetworkModule {
+
+ @Singleton
+ @Provides
+ fun provideAuthService(retrofit: Retrofit): AuthService {
+ return retrofit.create(AuthService::class.java)
+ }
+
+ @Singleton
+ @Provides
+ fun provideUserService(retrofit: Retrofit): UserService {
+ return retrofit.create(UserService::class.java)
+ }
+
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/domain/usecase/DataStoreUseCase.kt b/common/src/main/java/com/example/common/domain/usecase/DataStoreUseCase.kt
new file mode 100644
index 0000000..2e577ee
--- /dev/null
+++ b/common/src/main/java/com/example/common/domain/usecase/DataStoreUseCase.kt
@@ -0,0 +1,58 @@
+package com.example.common.domain.usecase
+
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.intPreferencesKey
+import androidx.datastore.preferences.core.stringPreferencesKey
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import androidx.datastore.preferences.core.Preferences
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class DataStoreUseCase @Inject constructor(
+ private val dataStore: DataStore
+) {
+
+
+ val bearerJsonWebToken: Flow =
+ dataStore.data.map { preferences -> preferences[jsonWebToken_key]?.toBearerToken() }
+
+ val myCode: Flow =
+ dataStore.data.map { preferences -> preferences[user_code] }
+
+ val permissionNum: Flow =
+ dataStore.data.map { preferences -> preferences[permission_num] }
+
+ private fun String.toBearerToken(): String = "Bearer $this"
+
+
+ suspend fun editJsonWebToken(jwt: String) {
+ dataStore.edit {
+ it[jsonWebToken_key] = jwt
+ }
+ }
+
+ suspend fun editUserCode(userCode: String) {
+ dataStore.edit {
+ it[user_code] = userCode
+ }
+ }
+
+ suspend fun editPermissionNum(num: Int) {
+ dataStore.edit {
+ it[permission_num] = num
+ }
+ }
+
+
+ companion object {
+ const val DATA_STORE_NAME = "app"
+
+ private val jsonWebToken_key = stringPreferencesKey("JSON_WEB_TOKEN")
+ private val permission_num = intPreferencesKey("PERMISSION_NUM")
+ private val user_code = stringPreferencesKey("USER_CODE")
+ }
+
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/domain/usecase/UserUseCase.kt b/common/src/main/java/com/example/common/domain/usecase/UserUseCase.kt
new file mode 100644
index 0000000..852b0cd
--- /dev/null
+++ b/common/src/main/java/com/example/common/domain/usecase/UserUseCase.kt
@@ -0,0 +1,17 @@
+package com.example.common.domain.usecase
+
+import com.example.common.data.dto.HomeResponse
+import com.example.common.data.source.UserService
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+import javax.inject.Singleton
+
+//todo Singletone?
+@Singleton
+class UserUseCase @Inject constructor(
+ private val userService: UserService
+) {
+// suspend fun getHomeData(token: String): HomeResponse {
+// return userService.getHomeInfo(token)
+// }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/example/common/util/Constant.kt b/common/src/main/java/com/example/common/util/Constant.kt
new file mode 100644
index 0000000..f951182
--- /dev/null
+++ b/common/src/main/java/com/example/common/util/Constant.kt
@@ -0,0 +1,3 @@
+package com.example.common.util
+
+const val NATIVE_APP_KEY = "5162225c94277a85e12566f227145303"
\ No newline at end of file
diff --git a/common/src/test/java/com/example/common/ExampleUnitTest.kt b/common/src/test/java/com/example/common/ExampleUnitTest.kt
new file mode 100644
index 0000000..6c9f3e0
--- /dev/null
+++ b/common/src/test/java/com/example/common/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.common
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/foundation/.gitignore b/foundation/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/foundation/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/foundation/build.gradle b/foundation/build.gradle
new file mode 100644
index 0000000..061e898
--- /dev/null
+++ b/foundation/build.gradle
@@ -0,0 +1,53 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+ id 'kotlin-kapt'
+ id 'com.google.dagger.hilt.android'
+}
+
+android {
+ namespace 'com.example.foundation'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 23
+ targetSdk 33
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ // Retrofit2
+ api "com.squareup.okhttp3:okhttp:$rootProject.okHttpVersion"
+ api "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttpVersion"
+ api "com.squareup.retrofit2:retrofit:$rootProject.retrofit2Version"
+ api "com.squareup.retrofit2:converter-gson:$rootProject.retrofit2Version"
+
+ // Hilt
+ implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
+ kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
+
+ implementation 'androidx.core:core-ktx:1.9.0'
+ implementation 'androidx.appcompat:appcompat:1.6.0'
+ implementation 'com.google.android.material:material:1.8.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
\ No newline at end of file
diff --git a/foundation/consumer-rules.pro b/foundation/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/foundation/proguard-rules.pro b/foundation/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/foundation/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/foundation/src/androidTest/java/com/example/foundation/ExampleInstrumentedTest.kt b/foundation/src/androidTest/java/com/example/foundation/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..8379c8f
--- /dev/null
+++ b/foundation/src/androidTest/java/com/example/foundation/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.foundation
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.foundation.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/foundation/src/main/AndroidManifest.xml b/foundation/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/foundation/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/foundation/src/main/java/com/example/foundation/di/NetworkModule.kt b/foundation/src/main/java/com/example/foundation/di/NetworkModule.kt
new file mode 100644
index 0000000..868a0d8
--- /dev/null
+++ b/foundation/src/main/java/com/example/foundation/di/NetworkModule.kt
@@ -0,0 +1,41 @@
+package com.example.foundation.di
+
+import com.example.foundation.util.BASE_URL
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class NetworkModule {
+
+ @Provides
+ fun provideBaseUrl() = BASE_URL
+
+ @Singleton
+ @Provides
+ fun provideOkHttpClient(): OkHttpClient {
+ val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
+ return OkHttpClient.Builder()
+ .addInterceptor(logger)
+ .build()
+ }
+
+ @Singleton
+ @Provides
+ fun provideRetrofit(
+ okHttpClient: OkHttpClient,
+ baseUrl: String
+ ): Retrofit = Retrofit.Builder()
+ .baseUrl(baseUrl)
+ .client(okHttpClient)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+
+}
\ No newline at end of file
diff --git a/foundation/src/main/java/com/example/foundation/util/Constant.kt b/foundation/src/main/java/com/example/foundation/util/Constant.kt
new file mode 100644
index 0000000..3fb9bfe
--- /dev/null
+++ b/foundation/src/main/java/com/example/foundation/util/Constant.kt
@@ -0,0 +1,4 @@
+package com.example.foundation.util
+
+const val BASE_URL = "http://13.125.67.47:18080/"
+
diff --git a/foundation/src/test/java/com/example/foundation/ExampleUnitTest.kt b/foundation/src/test/java/com/example/foundation/ExampleUnitTest.kt
new file mode 100644
index 0000000..756bb8c
--- /dev/null
+++ b/foundation/src/test/java/com/example/foundation/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.foundation
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/home/build.gradle b/home/build.gradle
index 3dbca2a..8f10e2d 100644
--- a/home/build.gradle
+++ b/home/build.gradle
@@ -1,6 +1,8 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
+ id 'kotlin-kapt'
+ id 'com.google.dagger.hilt.android'
}
android {
@@ -35,6 +37,14 @@ android {
dependencies {
+ api project(path: ':common-ui')
+ api project(path: ':common')
+
+
+ // Hilt
+ implementation "com.google.dagger:hilt-android:$rootProject.hiltVersion"
+ kapt "com.google.dagger:hilt-android-compiler:$rootProject.hiltVersion"
+
api project(path: ':common-ui')
implementation 'androidx.core:core-ktx:1.9.0'
diff --git a/home/src/main/AndroidManifest.xml b/home/src/main/AndroidManifest.xml
index a5918e6..16b8f6e 100644
--- a/home/src/main/AndroidManifest.xml
+++ b/home/src/main/AndroidManifest.xml
@@ -1,4 +1,6 @@
+
+
\ No newline at end of file
diff --git a/home/src/main/java/com/najudoryeong/mineme/home/HomeFragment.kt b/home/src/main/java/com/najudoryeong/mineme/home/HomeFragment.kt
index cf67f97..433f8a8 100644
--- a/home/src/main/java/com/najudoryeong/mineme/home/HomeFragment.kt
+++ b/home/src/main/java/com/najudoryeong/mineme/home/HomeFragment.kt
@@ -3,16 +3,38 @@ package com.najudoryeong.mineme.home
import android.os.Bundle
import android.view.View
import androidx.activity.OnBackPressedCallback
+import androidx.activity.viewModels
+import androidx.fragment.app.viewModels
import com.najudoryeong.mineme.common_ui.BaseFragment
import com.najudoryeong.mineme.common_ui.MainActivityUtil
import com.najudoryeong.mineme.home.databinding.FragmentHomeBinding
+import dagger.hilt.android.AndroidEntryPoint
+@AndroidEntryPoint
class HomeFragment : BaseFragment(Home) {
+ private val viewModel: HomeViewModel by viewModels()
+
+
+
override fun initView() {
+ /*
+
+ 데이터 바인딩 객체의 라이플 사이클 오너를 프래그먼트의 라이프 사이클로 지정하는 것
+ 이렇게 해야 프래그먼트의 라이프 사이클이 끝날 때 까지 데이터 바인딩을 유지 하며 관찰 가능
+
+ 이 작업을 안하면 실시간 데이터 변경 적용 안될 수 있음
+
+ */
+
+ binding.lifecycleOwner =viewLifecycleOwner
+ binding.vm = viewModel
//todo recycle
+
+ viewModel.settingHomeData()
+
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
activity?.finish()
@@ -22,5 +44,11 @@ class HomeFragment : BaseFragment(Home) {
requireActivity().onBackPressedDispatcher.addCallback(
viewLifecycleOwner, callback
)
+
+
+
+
}
+
+
}
\ No newline at end of file
diff --git a/home/src/main/java/com/najudoryeong/mineme/home/HomeViewModel.kt b/home/src/main/java/com/najudoryeong/mineme/home/HomeViewModel.kt
index 0dff213..071922a 100644
--- a/home/src/main/java/com/najudoryeong/mineme/home/HomeViewModel.kt
+++ b/home/src/main/java/com/najudoryeong/mineme/home/HomeViewModel.kt
@@ -1,7 +1,54 @@
package com.najudoryeong.mineme.home
+import android.content.Context
+import android.util.Log
+import androidx.databinding.Bindable
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.common.data.dto.HomeResponse
+import com.example.common.data.entity.HomeData
+import com.example.common.data.source.AuthService
+import com.example.common.data.source.UserService
+import com.example.common.domain.usecase.DataStoreUseCase
+import dagger.hilt.android.lifecycle.HiltViewModel
+import dagger.hilt.android.qualifiers.ApplicationContext
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import javax.inject.Inject
-class HomeViewModel : ViewModel() {
+@HiltViewModel
+class HomeViewModel @Inject constructor(
+ @ApplicationContext private val context: Context,
+ private val userService: UserService,
+ private val dataStoreUseCase: DataStoreUseCase
+) : ViewModel() {
+
+ private val _isNewStory = MutableStateFlow(true)
+ val isNewStory : StateFlow = _isNewStory
+
+ private val _homeData = MutableStateFlow(null)
+ val homeData: StateFlow = _homeData
+
+
+ fun settingHomeData() {
+ viewModelScope.launch {
+ var a = dataStoreUseCase.bearerJsonWebToken.first()
+ if (a == null) a = "bearer test"
+ userService.getHomeInfo(a).let {
+ if (it.success){
+ Log.d("TESTAPI","API넣음")
+ if (it.data.newStory.postId == -1){
+ _isNewStory.value = true
+ }
+ _homeData.value = it.data
+
+ } else {
+ Log.d("TESTAPI","API실패")
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/home/src/main/res/layout/fragment_home.xml b/home/src/main/res/layout/fragment_home.xml
index 52190ce..814f833 100644
--- a/home/src/main/res/layout/fragment_home.xml
+++ b/home/src/main/res/layout/fragment_home.xml
@@ -4,6 +4,16 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -150,6 +188,25 @@
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/home_noStoryLayout" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
\ No newline at end of file
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputCodeFragment.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputCodeFragment.kt
index 7517fc8..0f1d51a 100644
--- a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputCodeFragment.kt
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputCodeFragment.kt
@@ -5,14 +5,19 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
+import com.example.common.data.dto.CodeRequest
import com.najudoryeong.mineme.common_ui.MainActivityUtil
import com.najudoryeong.mineme.onboarding.databinding.FragmentInputCodeBinding
+import dagger.hilt.android.AndroidEntryPoint
-
+@AndroidEntryPoint
class InputCodeFragment : Fragment() {
+ private val viewModel: SplashViewModel by viewModels()
+
private var _binding: FragmentInputCodeBinding? = null
private val binding get() = _binding!!
@@ -20,7 +25,7 @@ class InputCodeFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- _binding = FragmentInputCodeBinding.inflate(inflater,container,false)
+ _binding = FragmentInputCodeBinding.inflate(inflater, container, false)
return binding.root
}
@@ -30,14 +35,14 @@ class InputCodeFragment : Fragment() {
binding.nextButton.setOnClickListener {
-// (activity as MainActivityUtil).run {
-// navigate(this@InputCodeFragment,Home)
-// }
- (activity as MainActivityUtil).run {
- navigateToHome(this@InputCodeFragment)
+ viewModel.getJsonWebToken { JWT ->
+ viewModel.inputCode(
+ JWT!!,CodeRequest(binding.code.text.toString())
+ ){
+ (requireActivity() as SplashActivity).startHomeActivity()
+ }
}
}
-
}
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputUserInfoFragment.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputUserInfoFragment.kt
index ddcbc46..f70360d 100644
--- a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputUserInfoFragment.kt
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/InputUserInfoFragment.kt
@@ -5,14 +5,19 @@ import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
+import com.example.common.data.dto.UserInfoRequest
import com.najudoryeong.mineme.common_ui.MainActivityUtil
import com.najudoryeong.mineme.onboarding.databinding.FragmentInputUserInfoBinding
import com.najudoryeong.mineme.onboarding.databinding.FragmentLoginBinding
+import dagger.hilt.android.AndroidEntryPoint
-
+@AndroidEntryPoint
class InputUserInfoFragment : Fragment() {
+ private val viewModel: SplashViewModel by viewModels()
+
private var _binding: FragmentInputUserInfoBinding? = null
private val binding get() = _binding!!
@@ -20,18 +25,18 @@ class InputUserInfoFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- _binding = FragmentInputUserInfoBinding.inflate(inflater,container,false)
+ _binding = FragmentInputUserInfoBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
-
binding.nextButton.setOnClickListener {
- findNavController().navigate(R.id.next)
+ viewModel.getJsonWebToken { JWT ->
+ viewModel.inputUserInfo(JWT!!,UserInfoRequest(binding.userName.text.toString(),binding.userBirthDay.text.toString())){
+ findNavController().navigate(R.id.next)
+ }
+ }
}
-
}
-
}
\ No newline at end of file
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginFragment.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginFragment.kt
index 2ce0e26..96dc472 100644
--- a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginFragment.kt
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginFragment.kt
@@ -13,8 +13,10 @@ import com.najudoryeong.mineme.common_ui.MainActivityUtil
import com.najudoryeong.mineme.onboarding.R
import com.najudoryeong.mineme.onboarding.databinding.FragmentLoginBinding
import com.najudoryeong.mineme.onboarding.databinding.FragmentOnBoardingViewPagerBinding
+import dagger.hilt.android.AndroidEntryPoint
+@AndroidEntryPoint
class LoginFragment : Fragment() {
private var _binding: FragmentLoginBinding? = null
@@ -44,7 +46,7 @@ class LoginFragment : Fragment() {
)
binding.kakaoLoginBtn.setOnClickListener {
- findNavController().navigate(R.id.next)
+ (requireActivity() as SplashActivity).checkJWT()
}
}
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginUtil.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginUtil.kt
new file mode 100644
index 0000000..5292be4
--- /dev/null
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/LoginUtil.kt
@@ -0,0 +1,74 @@
+package com.najudoryeong.mineme.onboarding
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import com.kakao.sdk.auth.model.OAuthToken
+import com.kakao.sdk.common.model.ClientError
+import com.kakao.sdk.common.model.ClientErrorCause
+import com.kakao.sdk.user.UserApiClient
+
+class LoginUtil {
+
+
+ companion object {
+
+ fun startMainActivity(activity: Activity, mainActivityClass: Class<*>) {
+ val intent = Intent(activity, mainActivityClass).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
+ }
+ activity.startActivity(intent)
+ }
+
+ fun loginWithKaKao(
+ context: Context,
+ onLoginSuccess: (String?) -> Unit
+ ) {
+
+ // 카카오계정으로 로그인 공통 callback 구성
+ // 카카오톡으로 로그인 할 수 없어 카카오계정으로 로그인할 경우 사용됨
+ val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
+ if (error != null) {
+ Log.d("errorLogin",error.toString())
+ } else {
+ onLoginSuccess(token?.accessToken)
+ // 카카오 계정으로 로그인 성공
+ }
+ }
+
+ // 카카오톡이 설치되어 있으면 카카오톡 로그인, 아니면 카카오계정으로 로그인
+ Log.d("errorLogin",UserApiClient.instance.isKakaoTalkLoginAvailable(context).toString())
+ if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
+ UserApiClient.instance.loginWithKakaoTalk(context) { token, error ->
+ if (error != null) {
+ // 카카오톡 로그인 실패
+
+ //사용자가 카카오톡 설치 후 디바이스 권한 요청화면에서 로그인을 취소한 경우
+ // 의도적 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리
+ if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
+ // todo 그대로
+ // 로그인 취소하셨습니다.
+ return@loginWithKakaoTalk
+ }
+
+ // 카카오톡에 연결된 카카오 계정이 없으면 카카오계정 로그인 시도
+ UserApiClient.instance.loginWithKakaoAccount(context, callback = callback)
+ } else if (token != null) {
+ // 카카오톡로그인 로그인 성공
+ onLoginSuccess(token.accessToken)
+ }
+
+ }
+ } else {
+ //카카오톡 설치 x => 카카오 계정으로 로그인
+ UserApiClient.instance.loginWithKakaoAccount(context, callback = callback)
+
+ }
+
+
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/OnBoardingViewPagerFragment.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/OnBoardingViewPagerFragment.kt
index 66b642a..17fe269 100644
--- a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/OnBoardingViewPagerFragment.kt
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/OnBoardingViewPagerFragment.kt
@@ -1,64 +1,100 @@
package com.najudoryeong.mineme.onboarding
+import android.Manifest
+import android.os.Build
import android.os.Bundle
-import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter
-import com.najudoryeong.mineme.common_ui.MainActivityUtil
+import com.google.android.material.snackbar.Snackbar
+import com.najudoryeong.mineme.common_ui.DialogForPermission
import com.najudoryeong.mineme.onboarding.databinding.FragmentOnBoardingViewPagerBinding
import com.najudoryeong.mineme.onboarding.viewpagerfragment.OnBoarding1Fragment
import com.najudoryeong.mineme.onboarding.viewpagerfragment.OnBoarding2Fragment
import com.najudoryeong.mineme.onboarding.viewpagerfragment.OnBoarding3Fragment
+import dagger.hilt.android.AndroidEntryPoint
-private const val NUM_PAGES = 3
+@AndroidEntryPoint
class OnBoardingViewPagerFragment : Fragment() {
+ companion object{
+ var viewpagerNum = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) 3 else 2
+ }
+
+ private val viewModel: SplashViewModel by viewModels()
+
//todo ViewBindingPropertyDelegate
private var _binding: FragmentOnBoardingViewPagerBinding? = null
private val binding get() = _binding!!
+ //todo companion?
+ private val messageArray = arrayOf("gps 권한", "알림 권한", "카메라 권한")
+ private val imageArray = arrayOf(R.drawable.img_gps, R.drawable.img_gps, R.drawable.img_gps)
+ private val permissionArray = arrayOf(
+ arrayOf(
+ Manifest.permission.ACCESS_COARSE_LOCATION, // 도시 블록 단위
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ ),
+ arrayOf(Manifest.permission.CAMERA),
+ arrayOf(Manifest.permission.POST_NOTIFICATIONS)
+ )
+
+
+ private val requestPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) { permissions ->
+ if (permissions.all { it.value }) {
+ if (binding.viewPager2.currentItem == viewpagerNum - 1) {
+ findNavController().navigate(R.id.next)
+ viewModel.setViewPagerNum(viewpagerNum)
+ }
+ binding.viewPager2.currentItem++
+ } else {
+ Snackbar.make(binding.root, "앱을 사용하기 위해 권한 허용을 해주세요!", Snackbar.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun requestPermission(permissionArray: Array) =
+ requestPermissionLauncher.launch(permissionArray)
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentOnBoardingViewPagerBinding.inflate(inflater, container, false)
- hideAppBar()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-
binding.viewPager2.let {
it.adapter = OnBoardingViewPagerAdapter(this)
binding.indicator.setViewPager(it)
}
binding.nextButton.setOnClickListener {
- Log.d("page", "${binding.viewPager2.currentItem - 1}")
- if (binding.viewPager2.currentItem == NUM_PAGES - 1)
- findNavController().navigate(R.id.next)
- else
- binding.viewPager2.currentItem++
- }
- }
+ val index = binding.viewPager2.currentItem
+
+ DialogForPermission.Builder(requireContext())
+ .setMessage(messageArray[index])
+ .setImg(imageArray[index])
+ .setOnClickButton {
+ requestPermission(permissionArray[index])
+ }.build().show()
- private fun hideAppBar() {
- (activity as MainActivityUtil).run {
- setVisibilityBottomAppbar(View.GONE)
- }
- (activity as MainActivityUtil).run {
- setVisibilityTopAppBar(View.GONE)
}
+
}
+
override fun onDestroyView() {
super.onDestroyView()
_binding = null
@@ -67,7 +103,7 @@ class OnBoardingViewPagerFragment : Fragment() {
private inner class OnBoardingViewPagerAdapter(fragment: Fragment) :
FragmentStateAdapter(fragment) {
- override fun getItemCount(): Int = NUM_PAGES
+ override fun getItemCount(): Int = viewpagerNum
override fun createFragment(position: Int): Fragment {
return when (position) {
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashActivity.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashActivity.kt
index 3c7960e..b1e6fe9 100644
--- a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashActivity.kt
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashActivity.kt
@@ -1,50 +1,77 @@
package com.najudoryeong.mineme.onboarding
+import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
+import androidx.navigation.NavController
+import androidx.navigation.fragment.NavHostFragment
import com.najudoryeong.mineme.onboarding.databinding.ActivitySplashBinding
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
+@SuppressLint("CustomSplashScreen")
@AndroidEntryPoint
class SplashActivity : AppCompatActivity() {
+ private lateinit var navController: NavController
private lateinit var binding: ActivitySplashBinding
+ private val viewModel: SplashViewModel by viewModels()
- /** inject from [MainModule] in AppModule */
- @Inject
- lateinit var mainActivityClass: Class<*>
-
+ @Inject lateinit var mainActivityClass: Class<*>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ checkJWT()
binding = DataBindingUtil.setContentView(this, R.layout.activity_splash)
- if (!checkAuth()) startOnBoarding()
- if (!checkLogin()) startLogin()
- startMainActivity()
}
- // 권한 동의와 로그인이 됐다면 바로 홈 화면으로 이동 아니면 권한 및 로그인화면 이동
- private fun checkAuth(): Boolean {
- //todo 권한 체크
- return true
- }
- private fun checkLogin() : Boolean{
- //todo 로그인 체크
- return true
+ // todo Viewmodel에 가지고 있는 datastore객체에 값을 가져오면 실행할 callback을 정의해서 viewModel에 넘긴다
+ fun checkJWT() {
+ Log.d("test", "checkJWT")
+ viewModel.getJsonWebToken { JWT ->
+ if (JWT != null) {
+ startHomeActivity()
+ } else {
+ isFirst { permissionNum ->
+ // 처음이아님 => 카카오 로그인만 다시
+ if (permissionNum == OnBoardingViewPagerFragment.viewpagerNum) {
+ LoginUtil.loginWithKaKao(this) { token ->
+ viewModel.signup(token = token!!) {
+ // 로그인 됐다면 다시 jwt 확인
+ checkJWT()
+ }
+ }
+ } else {
+ //처음이면 온보딩
+ initNav()
+ }
+ }
+ }
+ }
}
- private fun startMainActivity() {
- val intent = Intent(this, mainActivityClass)
- startActivity(intent)
+ fun startHomeActivity(){
+ LoginUtil.startMainActivity(this,mainActivityClass)
}
- private fun startLogin() {
- //todo login 처리 프로세스
+ private fun initNav() {
+ val navHostFragment =
+ supportFragmentManager.findFragmentById(R.id.fragment_containerView) as NavHostFragment
+ navController = navHostFragment.navController
+ binding.splashScreen.visibility = View.GONE
+ binding.fragmentContainerView.visibility = View.VISIBLE
}
- private fun startOnBoarding(){
- //todo onBoarding 프로세스
+
+ //todo 최초 접속인지 즉 온보딩안했는지
+ private fun isFirst(callback: (Int?) -> Unit) {
+ viewModel.checkPermission { permissionNum ->
+ callback.invoke(permissionNum)
+ }
}
+
}
\ No newline at end of file
diff --git a/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashViewModel.kt b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashViewModel.kt
new file mode 100644
index 0000000..af0c95f
--- /dev/null
+++ b/onboarding/src/main/java/com/najudoryeong/mineme/onboarding/SplashViewModel.kt
@@ -0,0 +1,86 @@
+package com.najudoryeong.mineme.onboarding
+
+import android.content.Context
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.common.data.dto.CodeRequest
+import com.example.common.data.dto.UserInfoRequest
+import com.example.common.data.source.AuthService
+import com.example.common.data.source.UserService
+import com.example.common.domain.usecase.DataStoreUseCase
+import dagger.hilt.android.lifecycle.HiltViewModel
+import dagger.hilt.android.qualifiers.ApplicationContext
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class SplashViewModel @Inject constructor(
+ @ApplicationContext private val context: Context,
+ private val authService: AuthService,
+ private val userService: UserService,
+ private val dataStoreUseCase: DataStoreUseCase
+) : ViewModel() {
+
+ fun getJsonWebToken(callback: (String?) -> Unit) {
+ viewModelScope.launch {
+ callback.invoke(dataStoreUseCase.bearerJsonWebToken.first())
+ }
+ }
+
+ fun checkPermission(callback: (Int) -> Unit) {
+ viewModelScope.launch {
+ val permissionNum = dataStoreUseCase.permissionNum.first()
+ if (permissionNum != null) {
+ callback.invoke(permissionNum)
+ } else {
+ callback.invoke(0)
+ }
+ }
+ }
+
+ fun setViewPagerNum(num: Int) {
+ viewModelScope.launch {
+ dataStoreUseCase.editPermissionNum(num)
+ }
+ }
+
+
+ fun signup(token: String, callback: () -> Unit) {
+ viewModelScope.launch {
+ dataStoreUseCase.editJsonWebToken("testtoken123")
+ dataStoreUseCase.editUserCode("testcode123")
+ callback.invoke()
+
+ /*
+ //todo userName
+ authService.login(LoginRequest(token,ProviderType.KAKAO.name,"test123")).let {
+ if (it.success) {
+ dataStoreUseCase.editJsonWebToken(it.data.jwt)
+ dataStoreUseCase.editUserCode(it.data.code)
+ callback.invoke()
+ }
+ }
+ */
+
+ }
+ }
+
+ fun inputUserInfo(token: String, userInfoRequest: UserInfoRequest, callback: () -> Unit) {
+ viewModelScope.launch {
+ userService.postUserInfo(token, userInfoRequest).let {
+ if (it.success) {
+ callback.invoke()
+ }
+ }
+ }
+ }
+
+ fun inputCode(token: String, codeRequest: CodeRequest, callback: () -> Unit) {
+ viewModelScope.launch {
+ userService.postTargetCode(token, codeRequest).let {
+ if (it.success) callback.invoke()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/onboarding/src/main/res/drawable/img_gps.xml b/onboarding/src/main/res/drawable/img_gps.xml
new file mode 100644
index 0000000..7af571e
--- /dev/null
+++ b/onboarding/src/main/res/drawable/img_gps.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
diff --git a/onboarding/src/main/res/layout/activity_splash.xml b/onboarding/src/main/res/layout/activity_splash.xml
index 762160f..a5f2842 100644
--- a/onboarding/src/main/res/layout/activity_splash.xml
+++ b/onboarding/src/main/res/layout/activity_splash.xml
@@ -3,21 +3,36 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
-
+ tools:context=".SplashActivity">
+
+
+
-
+
+
+ android:visibility="gone"
+ app:defaultNavHost="true"
+ app:navGraph="@navigation/nav_onboarding" />
+
-
+
diff --git a/onboarding/src/main/res/layout/fragment_input_code.xml b/onboarding/src/main/res/layout/fragment_input_code.xml
index 9cf83db..f5008c0 100644
--- a/onboarding/src/main/res/layout/fragment_input_code.xml
+++ b/onboarding/src/main/res/layout/fragment_input_code.xml
@@ -10,12 +10,19 @@
+
+
+
+
+
+
+