diff --git a/.gitignore b/.gitignore
index ad4cf3e..0fe447f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,10 +4,12 @@
/local.properties
/.idea/caches
/.idea/libraries
+/.idea/.name
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
+/.idea/deploymentTargetDropDown.xml
.DS_Store
/build
/captures
@@ -39,4 +41,3 @@ local.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
-
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 460bbdd..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Apic
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index b589d56..fb7f4a8 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index ae388c2..6d4d622 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -7,11 +7,12 @@
-
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4412b1a..a460dc7 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,7 @@
-
-
+
+
diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_01__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_01__Changes_.xml
new file mode 100644
index 0000000..0358942
--- /dev/null
+++ b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_01__Changes_.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_02__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_02__Changes_.xml
new file mode 100644
index 0000000..4c35eed
--- /dev/null
+++ b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25__2_02__Changes_.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git "a/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25_\354\230\244\355\233\204_2_01_[Changes]/shelved.patch" "b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25_\354\230\244\355\233\204_2_01_[Changes]/shelved.patch"
new file mode 100644
index 0000000..e69de29
diff --git "a/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25_\354\230\244\355\233\204_2_02_[Changes]/shelved.patch" "b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25_\354\230\244\355\233\204_2_02_[Changes]/shelved.patch"
new file mode 100644
index 0000000..57efc7a
--- /dev/null
+++ "b/.idea/shelf/Uncommitted_changes_before_Checkout_at_2023-11-25_\354\230\244\355\233\204_2_02_[Changes]/shelved.patch"
@@ -0,0 +1,19 @@
+Index: .idea/misc.xml
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
+<+>\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+diff --git a/.idea/misc.xml b/.idea/misc.xml
+--- a/.idea/misc.xml (revision 559aba0c29d96e6d12bd8e1c8df4f32f10d34323)
++++ b/.idea/misc.xml (date 1700888503945)
+@@ -1,7 +1,7 @@
+
+
+
+-
++
+
+
+
diff --git "a/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23,_1_39\342\200\257PM_[Changes]/shelved.patch" "b/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23,_1_39\342\200\257PM_[Changes]/shelved.patch"
new file mode 100644
index 0000000..e146616
--- /dev/null
+++ "b/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23,_1_39\342\200\257PM_[Changes]/shelved.patch"
@@ -0,0 +1,23 @@
+Index: app/src/main/java/com/Apic/apic/MainActivity.kt
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
+<+>package com.Apic.apic\n\n\nimport android.content.Intent\nimport androidx.appcompat.app.AppCompatActivity\nimport android.os.Bundle\nimport com.Apic.apic.databinding.ActivityMainBinding\nimport androidx.fragment.app.FragmentManager\nimport androidx.fragment.app.FragmentTransaction\nimport com.google.android.material.bottomnavigation.BottomNavigationView\n\nclass MainActivity : AppCompatActivity() {\n lateinit var binding: ActivityMainBinding\n\n private val fragmentManager: FragmentManager = supportFragmentManager\n private val fragmentCalendar = CalendarFragment()\n private val fragmentFriend = FriendFragment()\n private val GroupListActivity = GroupListActivity()\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n\n binding = ActivityMainBinding.inflate(layoutInflater)\n setContentView(binding.root)\n\n setSupportActionBar(findViewById(R.id.toolbar)) // 뒤로가기 메뉴\n\n val transaction: FragmentTransaction = fragmentManager.beginTransaction()\n transaction.replace(R.id.menu_frame_view, fragmentCalendar).commitAllowingStateLoss()\n\n val bottomNavigationView = findViewById(R.id.bottom_navigationview)\n bottomNavigationView.setOnNavigationItemSelectedListener { menuItem ->\n val transaction = fragmentManager.beginTransaction()\n\n when (menuItem.itemId) {\n R.id.menu_home -> transaction.replace(R.id.menu_frame_view, fragmentCalendar).commitAllowingStateLoss()\n R.id.menu_friend -> transaction.replace(R.id.menu_frame_view, fragmentFriend).commitAllowingStateLoss()\n R.id.menu_share -> {\n val intent = Intent(this, GroupListActivity::class.java)\n startActivity(intent)\n }\n }\n true\n }\n\n // group activity test code\n val intent = Intent(this, GroupActivity::class.java)\n startActivity(intent)\n finish()\n\n }\n\n}
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+diff --git a/app/src/main/java/com/Apic/apic/MainActivity.kt b/app/src/main/java/com/Apic/apic/MainActivity.kt
+--- a/app/src/main/java/com/Apic/apic/MainActivity.kt (revision 0085522fd05b6d49900a62f19fbd11bdf05424da)
++++ b/app/src/main/java/com/Apic/apic/MainActivity.kt (date 1700627154050)
+@@ -44,9 +44,9 @@
+ }
+
+ // group activity test code
+- val intent = Intent(this, GroupActivity::class.java)
+- startActivity(intent)
+- finish()
++ // val intent = Intent(this, GroupActivity::class.java)
++ // startActivity(intent)
++ // finish()
+
+ }
+
diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23__1_39PM__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23__1_39PM__Changes_.xml
new file mode 100644
index 0000000..e1d87da
--- /dev/null
+++ b/.idea/shelf/Uncommitted_changes_before_Update_at_11_22_23__1_39PM__Changes_.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 735b550..a2e860a 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,70 @@
-# AppPicProj
\ No newline at end of file
+# AppPicProj
+
+
+
+
+# AppPic
+> **덕성여대 소프트웨어공학 3팀** **개발기간: 2023.09 ~ 2023.11**
+
+## 깃헙 산출물
+
+
+
+
+> **개발 버전** : [https://github.com/BaileyChoi/AppPicProj.git](https://github.com/BaileyChoi/AppPicProj.git)
+
+## 앱개발팀 소개
+
+| 헤이 | 깡지 | 말이 | 도도 | 호요요 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------:|
+| | | | | |
+| [@BaileyChoi](https://github.com/BaileyChoi) | [@dontworrywony](https://github.com/dontworrywony) | [@nar0ng](https://github.com/nar0ng) | [@hyunn0121](https://github.com/hyunn0121) | [@19013na](https://github.com/19013na) |
+| PM | Design | Infra | Developer | Developer |
+
+## 프로젝트 소개
+
+저희 AppPic에서 만든 PicTogether라는 어플은 기존의 모임어플에서의 불편함을 느껴 사용자들이 더 편리하게 모임을 관리하고 사진을 공유할 수 있도록 하기 위해 개발되었습니다.
+
+---
+
+## Stacks 🐈
+
+### Environment
+
+
+
+
+
+
+
+### Development
+
+
+
+### Communication
+
+
+
+---
+## 화면 구성 📺
+| 홈 페이지 | 친구 페이지 |
+|:------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------:|
+| | |
+| 모임 페이지 | 네컷 페이지 |
+| | |
+
+---
+## 주요 기능 📦
+
+### ⭐️ 약속 캘린더 기능
+- 캘린더에 약속을 추가하여 언제 어떤 약속이 있는지 한눈에 확인 가능
+
+### ⭐️ 친구 검색 및 추가 기능
+- PicTogether을 사용하는 회원 중 친구를 검색하여 친구 목록에 추가 가능
+
+### ⭐️ 모임 관리 및 모임 공유 사진첩 기능
+- 친구목록에서 원하는 친구를 골라 모임명과 함께 모임을 생성하고 목록에서 관리 가능
+- 공유하고 싶은 사진을 갤러리에서 골라 모임 공유 사진첩에 업로드 가능
+
+### ⭐️ 사진 편집 기능
+- 네컷사진의 프레임 색상을 변경하거나 다양한 효과를 적용하여 저장 가능
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index f5ad898..f333a77 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,6 +4,9 @@ plugins {
id 'com.google.gms.google-services'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+
}
android {
@@ -44,6 +47,7 @@ android {
}
buildFeatures {
compose true
+ viewBinding = true
}
composeOptions {
kotlinCompilerExtensionVersion '1.4.3'
@@ -52,15 +56,26 @@ android {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
+ pickFirst 'lib/arm64-v8a/libc++_shared.so'
+ pickFirst 'lib/x86/libc++_shared.so'
+ pickFirst 'lib/x86_64/libc++_shared.so'
+ pickFirst 'lib/armeabi -v7a/libc++_shared.so'
}
+
}
dependencies {
+ // OpenCV 4.5.1
+ implementation project(":opencv")
+
implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
+
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
implementation 'androidx.activity:activity-compose:1.8.0'
@@ -81,9 +96,26 @@ dependencies {
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
+ // glide
+ implementation 'com.github.bumptech.glide:glide:4.11.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
+
implementation(platform("com.google.firebase:firebase-bom:32.6.0"))
implementation 'com.google.firebase:firebase-auth-ktx:22.3.0'
+ implementation 'com.google.firebase:firebase-firestore:24.9.1'
// implementation 'com.google.android.gms:play-services-auth:20.7.0' // 구글 인증
+ implementation("androidx.lifecycle:lifecycle-runtime:2.6.0")
+ implementation "androidx.room:room-runtime:2.6.0"
+ kapt("androidx.room:room-compiler:2.6.0")
+ implementation("androidx.room:room-ktx:2.6.0")
+
+ implementation "androidx.lifecycle:lifecycle-viewmodel:2.3.1"
+ implementation "androidx.lifecycle:lifecycle-livedata:2.3.1"
+ kapt "androidx.lifecycle:lifecycle-compiler:2.3.1"
+}
+
+kapt {
+ generateStubs = true
}
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/example/appapicprj/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/appapicprj/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..ca7915c
--- /dev/null
+++ b/app/src/androidTest/java/com/example/appapicprj/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.appapicprj
+
+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.appapicprj", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 893347d..88e67d1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,11 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.Apic.apic">
+
+
+
+
+
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227.jpg
new file mode 100644
index 0000000..fd70212
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_01.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_01.jpg
new file mode 100644
index 0000000..5fc1d76
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_01.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_02.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_02.jpg
new file mode 100644
index 0000000..131cd44
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_02.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_03.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_03.jpg
new file mode 100644
index 0000000..9c957fb
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_03.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_04.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_04.jpg
new file mode 100644
index 0000000..dfe985f
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_04.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_05.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_05.jpg
new file mode 100644
index 0000000..dd5a052
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_05.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_06.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_06.jpg
new file mode 100644
index 0000000..03a6305
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_06.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_07.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_07.jpg
new file mode 100644
index 0000000..464f0ca
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_07.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_08.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_08.jpg
new file mode 100644
index 0000000..6625ae3
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_08.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_10.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_10.jpg
new file mode 100644
index 0000000..d2e71e9
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_10.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_11.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_11.jpg
new file mode 100644
index 0000000..910f25a
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_11.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_12.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_12.jpg
new file mode 100644
index 0000000..bebc299
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_12.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_13.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_13.jpg
new file mode 100644
index 0000000..8d30829
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_13.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_14.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_14.jpg
new file mode 100644
index 0000000..98bc55a
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_14.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_15.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_15.jpg
new file mode 100644
index 0000000..8593810
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_15.jpg differ
diff --git a/app/src/main/assets/KakaoTalk_20231128_191806227_16.jpg b/app/src/main/assets/KakaoTalk_20231128_191806227_16.jpg
new file mode 100644
index 0000000..fc6d78a
Binary files /dev/null and b/app/src/main/assets/KakaoTalk_20231128_191806227_16.jpg differ
diff --git a/app/src/main/assets/iv_fourcut_frame.png b/app/src/main/assets/iv_fourcut_frame.png
new file mode 100644
index 0000000..b094fa4
Binary files /dev/null and b/app/src/main/assets/iv_fourcut_frame.png differ
diff --git a/app/src/main/assets/iv_fourcut_frame_white.png b/app/src/main/assets/iv_fourcut_frame_white.png
new file mode 100644
index 0000000..8a0f733
Binary files /dev/null and b/app/src/main/assets/iv_fourcut_frame_white.png differ
diff --git a/app/src/main/assets/iv_fourcut_test_img.jpg b/app/src/main/assets/iv_fourcut_test_img.jpg
new file mode 100644
index 0000000..0cf83aa
Binary files /dev/null and b/app/src/main/assets/iv_fourcut_test_img.jpg differ
diff --git a/app/src/main/assets/shrimp_kang.jpg b/app/src/main/assets/shrimp_kang.jpg
new file mode 100644
index 0000000..7a7acbf
Binary files /dev/null and b/app/src/main/assets/shrimp_kang.jpg differ
diff --git a/app/src/main/java/com/Apic/apic/AddFriendFragment.kt b/app/src/main/java/com/Apic/apic/AddFriendFragment.kt
new file mode 100644
index 0000000..a919bb2
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/AddFriendFragment.kt
@@ -0,0 +1,185 @@
+package com.Apic.apic
+
+import android.content.Context
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.Log
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.EditText
+import android.widget.Toast
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.Apic.apic.databinding.FragmentAddFriendBinding
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.firestore.FirebaseFirestore
+
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+class AddFriendFragment : Fragment(), DialogAddFriendAdapter.OnAddFriendClickListener {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ private lateinit var auth: FirebaseAuth // 친구 리스트와 자신 email 비교를 위해 가져옴.
+ private lateinit var binding: FragmentAddFriendBinding
+ private val db = FirebaseFirestore.getInstance()
+ //private val itemList = arrayListOf()
+ private lateinit var editText: EditText
+ private val originalList: ArrayList = ArrayList()
+ private val searchList: ArrayList = ArrayList()
+ private var adapter = DialogAddFriendAdapter(originalList)
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentAddFriendBinding.inflate(inflater, container, false)
+ auth = FirebaseAuth.getInstance()
+
+ // Close Button click listener -> FriendFragment
+ binding.closeBtn.setOnClickListener {
+ (activity as? MainActivity)?.setFragment(0)
+ }
+
+ // Button click listener : search Friend email
+ binding.searchBtn.setOnClickListener{
+ val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.hideSoftInputFromWindow(binding.searchView.windowToken, 0)
+ }
+
+ editText = binding.searchView // 검색어 변수로 받음.
+
+ editText.addTextChangedListener(object : TextWatcher {
+ override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
+ // Optional: Add any functionality needed before text changes
+ }
+
+ override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
+ // Optional: Add any functionality needed during text changes
+ }
+
+
+ override fun afterTextChanged(editable: Editable) {
+ //Log.d("db", "addTextChangedListener")
+ val searchText = editText.text.toString().trim() //editable.toString()
+ //Log.d("db", "$searchText")
+ searchList.clear() // 검색 결과 갱신
+
+ if (searchText.isEmpty()) {
+ adapter.setFriendList(originalList)
+ } else {
+ // 검색 단어를 포함하는지 확인
+ for (a in 0 until originalList.size) {
+ //Log.d("db", "for loop: $a")
+ if (originalList[a].getName().toLowerCase().contains(searchText.toLowerCase())) {
+ searchList.add(originalList[a])
+ }
+ }
+
+ //dialogFriendAdapter.setFriendList(originalList)
+ adapter.setFriendList(searchList)
+ adapter.notifyDataSetChanged()
+ }
+ }
+ })
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.recyclerView.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
+ binding.recyclerView.adapter = adapter
+
+ // 친구 찾기에서 친구 리스트로 recyclerview로 뜨기
+ db.collection("memberDB") // Collection to work with
+ .get() // Get documents
+ .addOnSuccessListener { result ->
+ // On success
+ originalList.clear()
+ for (document in result) {
+ val item = MemberData(
+ document["email"] as String,
+ document["name"] as String,
+ //document["password"] as String
+ )
+ if (!auth.currentUser?.email.toString().equals(document["email"])) { // 현재 유저가 아닐때
+ originalList.add(item)
+ }
+ }
+ adapter.notifyDataSetChanged() // Update RecyclerView
+ }
+ .addOnFailureListener { exception ->
+ // On failure
+ Log.w("AddFriendFragment", "Error getting documents: $exception")
+ }
+
+
+ // add
+ //val adapter = DialogAddFriendAdapter(itemList)
+ adapter.setOnAddFriendClickListener(this) // Set the listener here
+ }
+
+ // checkBtn누르면 firestore에 친구 추가하기.
+ override fun onAddFriendClick(position: Int) {
+ val clickedItem = originalList[position]
+ Log.d("db", "Button clicked for ${clickedItem.name}") // add : 오류 확인을 위함
+ var name = clickedItem.name
+ var email = clickedItem.email
+ val reqFriendList = FriendList(email, name) //
+ //val resFriendList = FriendList(auth.currentUser?.email, auth.currentUser?.name) //
+ addFriend(reqFriendList)
+
+ Toast.makeText(requireContext(), "${clickedItem.name} : 친구 추가", Toast.LENGTH_SHORT).show()
+ }
+
+ // 친구 추가 하위 컬렉션 추가 : addFriend(friendData)
+ private fun addFriend(data: FriendList){
+ Log.d("db", "addFriend")
+ val db = FirebaseFirestore.getInstance()
+ db.collection("memberDB")
+ .document(auth.currentUser?.email.toString())
+ .collection("FriendList")
+ .document(data.email) // .add(data)해도 상관없음
+ .set(data)
+ .addOnSuccessListener {
+ Log.d("db", "success : addFriend")
+ }.addOnFailureListener{
+ Log.d("db", "fail : addFriend")
+ }
+ }
+ //
+
+companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment fragment_add_friend.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ AddFriendFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/AddGroupFragment.kt b/app/src/main/java/com/Apic/apic/AddGroupFragment.kt
index d435388..531ce1d 100644
--- a/app/src/main/java/com/Apic/apic/AddGroupFragment.kt
+++ b/app/src/main/java/com/Apic/apic/AddGroupFragment.kt
@@ -1,16 +1,17 @@
package com.Apic.apic
-import android.content.Intent
import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
+import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
import com.Apic.apic.databinding.FragmentAddGroupBinding
-import com.Apic.apic.databinding.FragmentGroupListBinding
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.firestore.FirebaseFirestore
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@@ -28,7 +29,15 @@ class AddGroupFragment : Fragment() {
private var param2: String? = null
private lateinit var binding: FragmentAddGroupBinding
+ private val db = FirebaseFirestore.getInstance()
+ private lateinit var auth: FirebaseAuth
+ private lateinit var groupParticipantsAdapter: GroupParticipantsAdapter
+
+ private val friendList = mutableListOf()
+
+ private val participantsList = mutableListOf()
+ private val participantsNameList = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -38,6 +47,21 @@ class AddGroupFragment : Fragment() {
}
}
+ // 친구 리스트에서 참여자 선택
+ private fun setOnClickEvent() {
+ groupParticipantsAdapter.setItemClickListener(object: GroupParticipantsAdapter.OnItemClickListener {
+ override fun onClick(view: View, position: Int) {
+ super.onClick(view, position)
+ Toast.makeText(view.context, "테스트 - ${friendList[position].f_name} 클릭", Toast.LENGTH_SHORT).show()
+ participantsList.add(friendList[position])
+ participantsNameList.add(friendList[position].f_name)
+ binding.groupParticipants.text = participantsNameList.toString()
+ binding.groupMemberNum.text = participantsNameList.size.toString()
+ }
+ })
+ }
+
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -45,22 +69,42 @@ class AddGroupFragment : Fragment() {
// Inflate the layout for this fragment
binding = FragmentAddGroupBinding.inflate(inflater, container, false)
+ auth = FirebaseAuth.getInstance()
+
+ val recyclerView: RecyclerView = binding.groupParticipantsRecyclerView
+ recyclerView.layoutManager = LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false)
+ groupParticipantsAdapter = GroupParticipantsAdapter(friendList)
+ recyclerView.adapter = groupParticipantsAdapter
+
+ getFriendData() // 친구 목록 불러오기
+
+ setOnClickEvent() // 참여자 선택
// 체크 버튼
binding.checkBtn.setOnClickListener {
- Toast.makeText(context, "모임 ${binding.EtGoupName.text}(${binding.groupMemberNum.text}명)가 생성되었습니다.", Toast.LENGTH_SHORT).show()
- // AddMeetingFragment 테스트용
- val transaction = fragmentManager?.beginTransaction()
- if (transaction != null) {
- transaction.replace(R.id.menu_frame_view, AddMeetingFragment()).commitAllowingStateLoss()
- }
+
// 그룹 추가
+ val gName = binding.EtGoupName.text.toString()
+ val gParticipants = participantsNameList.size.toString()
+
+ val groupData = GroupData(gName, gParticipants)
+ addGroup(groupData)
+
+ // 참여자 추가
+ for (participant in participantsList) {
+ val fName = participant.f_name
+ val fEmail = participant.f_email
+ val participantsData = FriendData(fName, fEmail)
+ addParticipants(groupData, participantsData)
+ }
+
+ Toast.makeText(context, "그룹 생성 완료", Toast.LENGTH_SHORT).show()
// 그룹 리스트로 돌아가기
-// val transaction = fragmentManager?.beginTransaction()
-// if (transaction != null) {
-// transaction.replace(R.id.menu_frame_view, GroupListFragment()).commitAllowingStateLoss()
-// }
+ val transaction = fragmentManager?.beginTransaction()
+ if (transaction != null) {
+ transaction.replace(R.id.menu_frame_view, GroupListFragment()).commitAllowingStateLoss()
+ }
}
// 엑스 버튼
@@ -75,8 +119,58 @@ class AddGroupFragment : Fragment() {
return binding.root
}
- private fun setOnClickListener() {
- val btnCheck = binding.checkBtn
+ private fun getFriendData() {
+ db.collection("memberDB")
+ .document(auth.currentUser!!.email.toString())
+ .collection("FriendList")
+ .get()
+ .addOnSuccessListener { result ->
+ friendList.clear()
+ for (document in result) {
+ val friend = FriendData (
+ document["email"] as String,
+ document["name"] as String
+ )
+ friendList.add(friend)
+ }
+ groupParticipantsAdapter.notifyDataSetChanged()
+ Log.d("db", "success")
+ }
+ .addOnFailureListener {
+ Log.d("db", "fail")
+ }
+ }
+
+ private fun addGroup(groupData: GroupData) {
+
+ db.collection("memberDB")
+ .document(auth.currentUser!!.email.toString())
+ .collection("groups")
+ .document(groupData.g_name)
+ .set(groupData)
+ .addOnCompleteListener {
+ Log.d("db", "success")
+ }
+ .addOnFailureListener {
+ Log.d("db", "fail")
+ }
+ }
+
+ private fun addParticipants(groupData: GroupData, participantsData: FriendData) {
+
+ db.collection("memberDB")
+ .document(auth.currentUser!!.email.toString())
+ .collection("groups")
+ .document(groupData.g_name)
+ .collection("participants")
+ .document(participantsData.f_email)
+ .set(participantsData)
+ .addOnCompleteListener {
+ Log.d("db", "success")
+ }
+ .addOnFailureListener {
+ Log.d("db", "fail")
+ }
}
companion object {
diff --git a/app/src/main/java/com/Apic/apic/AddMeetingFragment.kt b/app/src/main/java/com/Apic/apic/AddMeetingFragment.kt
index 962de3d..e9efe91 100644
--- a/app/src/main/java/com/Apic/apic/AddMeetingFragment.kt
+++ b/app/src/main/java/com/Apic/apic/AddMeetingFragment.kt
@@ -7,7 +7,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
-import com.Apic.apic.databinding.FragmentAddGroupBinding
import com.Apic.apic.databinding.FragmentAddMeetingBinding
// TODO: Rename parameter arguments, choose names that match
diff --git a/app/src/main/java/com/Apic/apic/AlbumAdapter.kt b/app/src/main/java/com/Apic/apic/AlbumAdapter.kt
new file mode 100644
index 0000000..fb6b15f
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/AlbumAdapter.kt
@@ -0,0 +1,45 @@
+package com.Apic.apic
+
+import android.content.Context
+import android.net.Uri
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+
+class AlbumAdapter() : RecyclerView.Adapter() {
+ lateinit var imageList: ArrayList
+ lateinit var context: Context
+
+ constructor(imageList: ArrayList, context: Context): this(){
+ this.imageList = imageList
+ this.context = context
+ }
+
+ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
+ val albumView: ImageView = view.findViewById(R.id.albumView)
+ }
+
+ // 화면 설정
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater: LayoutInflater = LayoutInflater.from(parent.context)
+ val view: View = inflater.inflate(R.layout.item_picture, parent, false)
+ return ViewHolder(view)
+ }
+
+ // 데이터 설정
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ Glide.with(context)
+ .load(imageList[position]) // 사진 위치
+ .into(holder.albumView) // 보여줄 위치
+ }
+
+ // 아이템 갯수
+ override fun getItemCount(): Int {
+ return imageList.size
+ }
+
+
+}
diff --git a/app/src/main/java/com/Apic/apic/AlbumFragment.kt b/app/src/main/java/com/Apic/apic/AlbumFragment.kt
new file mode 100644
index 0000000..2c3de26
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/AlbumFragment.kt
@@ -0,0 +1,89 @@
+package com.Apic.apic
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.Apic.apic.databinding.FragmentAlbumBinding
+
+class AlbumFragment : Fragment() {
+
+ private lateinit var binding: FragmentAlbumBinding
+ private lateinit var albumRecyclerView: RecyclerView
+
+ private var albumAdapter: AlbumAdapter? = null
+ private var imageList: ArrayList? = null
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // ViewBinding을 사용하여 프래그먼트의 레이아웃 설정
+ binding = FragmentAlbumBinding.inflate(inflater, container, false)
+ val rootView = binding.root
+
+ // RecyclerView 초기화 및 그리드 레이아웃 매니저 설정
+ albumRecyclerView = binding.albumRecyclerView
+ albumRecyclerView.layoutManager = GridLayoutManager(requireContext(), 3)
+
+ // 이미지 리스트가 null이면 새로 생성, 이미 있다면 기존 리스트 사용
+ imageList = imageList ?: ArrayList()
+
+ // AlbumAdapter 초기화 및 RecyclerView에 연결
+ albumAdapter = AlbumAdapter(imageList!!, requireContext())
+ albumRecyclerView.adapter = albumAdapter
+
+ Log.d("AlbumFragment", "onCreateView called")
+
+ return rootView
+ }
+
+ // MainActivity에서 호출하여 이미지 리스트 업데이트
+ fun updateImageList(data: Intent?) {
+ Log.d("AlbumFragment", "updateImageList called")
+
+ // 이미지 리스트가 null인 경우 새로 생성
+ if (imageList == null) {
+ imageList = ArrayList()
+ }
+
+ if (data?.clipData != null) { // 다중 이미지 선택 시
+ // 선택한 이미지의 갯수
+ Log.d("AlbumFragment", "ClipData exists with itemCount: ${data.clipData!!.itemCount}")
+ val count = data.clipData!!.itemCount
+
+ // 각 이미지를 리스트에 추가
+ for (index in 0 until count) {
+ val imageUri = data.clipData!!.getItemAt(index).uri
+ imageList?.add(imageUri)
+ Log.d("AlbumFragment", "Added image to imageList: $imageUri")
+ }
+ } else { // 단일 이미지 선택 시
+ Log.d("AlbumFragment", "ClipData is null")
+ val imageUri = data?.data
+ imageUri?.let {
+ imageList?.add(it)
+ }
+ }
+
+ // 이미지 리스트 업데이트
+ updateAdapter()
+ }
+
+ // RecyclerView 어댑터 업데이트 및 갱신
+ private fun updateAdapter() {
+ imageList?.let {
+ Log.d("AlbumFragment", "imageList size: ${it.size}")
+
+ // AlbumAdapter가 초기화되었는지 확인 후 notifyDataSetChanged 호출
+ albumAdapter?.notifyDataSetChanged()
+ Log.d("AlbumFragment", "notifyDataSetChanged")
+ }
+ }
+}
diff --git a/app/src/main/java/com/Apic/apic/CalendarFragment.kt b/app/src/main/java/com/Apic/apic/CalendarFragment.kt
index f4536ec..323f920 100644
--- a/app/src/main/java/com/Apic/apic/CalendarFragment.kt
+++ b/app/src/main/java/com/Apic/apic/CalendarFragment.kt
@@ -1,59 +1,90 @@
package com.Apic.apic
+
import android.os.Bundle
-import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Button
+import android.widget.CalendarView
+import android.widget.EditText
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.Apic.apic.data.Todo
-// TODO: Rename parameter arguments, choose names that match
-// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
-private const val ARG_PARAM1 = "param1"
-private const val ARG_PARAM2 = "param2"
+import kotlinx.coroutines.launch
+import java.util.Calendar
-/**
- * A simple [Fragment] subclass.
- * Use the [CalendarFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
class CalendarFragment : Fragment() {
- // TODO: Rename and change types of parameters
- private var param1: String? = null
- private var param2: String? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- arguments?.let {
- param1 = it.getString(ARG_PARAM1)
- param2 = it.getString(ARG_PARAM2)
- }
- }
+
+ private lateinit var recyclerView: RecyclerView
+ private lateinit var todoEditText: EditText
+ private lateinit var calendarView: CalendarView
+ private lateinit var addButton: Button
+
+ private lateinit var viewModel: MainViewModel
+ private var selectedDate: Long = 0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.fragment_calendar, container, false)
- }
+ val view = inflater.inflate(R.layout.fragment_calendar, container, false)
+
+ // 뷰 초기화
+ recyclerView = view.findViewById(R.id.recyclerView)
+ todoEditText = view.findViewById(R.id.todoEditText)
+ calendarView = view.findViewById(R.id.calendar)
+ addButton = view.findViewById(R.id.btnAdd)
+
+ // MainViewModel 초기화
+ viewModel = ViewModelProvider(requireActivity())[MainViewModel::class.java]
+
+ // RecyclerView 초기화
+ val layoutManager = LinearLayoutManager(requireContext())
+ layoutManager.reverseLayout = true
+ layoutManager.stackFromEnd = true
+ recyclerView.layoutManager = layoutManager
- companion object {
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment CalendarFragment.
- */
- // TODO: Rename and change types and number of parameters
- @JvmStatic
- fun newInstance(param1: String, param2: String) =
- CalendarFragment().apply {
- arguments = Bundle().apply {
- putString(ARG_PARAM1, param1)
- putString(ARG_PARAM2, param2)
- }
+ // Adapter 설정 부분은 그대로 유지
+ val adapter = TodoListAdapter { todo -> viewModel.deleteTodo(todo.id) }
+ recyclerView.adapter = adapter
+
+ // CalendarView 이벤트 핸들링
+ calendarView.setOnDateChangeListener { _, year, month, dayOfMonth ->
+ val calendar = Calendar.getInstance()
+ calendar.set(year, month, dayOfMonth)
+ selectedDate = calendar.timeInMillis
+ }
+
+ // 초기에 오늘 날짜로 선택되도록 설정
+ val today = Calendar.getInstance()
+ selectedDate = today.timeInMillis
+ calendarView.date = selectedDate
+
+ // "추가" 버튼 클릭 이벤트 처리
+ addButton.setOnClickListener {
+ val todoText = todoEditText.text.toString()
+ if (selectedDate != 0L && todoText.isNotBlank()) {
+ // Todo 객체 생성 및 저장
+ val newTodo = Todo(todoText, selectedDate)
+ viewModel.addTodo(newTodo)
+
+ // EditText 초기화
+ todoEditText.text.clear()
}
+ }
+
+ // ViewModel에서 데이터 관찰
+ viewLifecycleOwner.lifecycleScope.launch {
+ viewModel.items.collect { todos ->
+ adapter.submitList(todos)
+ }
+ }
+
+ return view
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/DateFragment.kt b/app/src/main/java/com/Apic/apic/DateFragment.kt
index 1e69712..fd8e429 100644
--- a/app/src/main/java/com/Apic/apic/DateFragment.kt
+++ b/app/src/main/java/com/Apic/apic/DateFragment.kt
@@ -1,6 +1,5 @@
package com.Apic.apic
-import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
diff --git a/app/src/main/java/com/Apic/apic/DialogAddFriendAdapter.kt b/app/src/main/java/com/Apic/apic/DialogAddFriendAdapter.kt
new file mode 100644
index 0000000..f73f224
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/DialogAddFriendAdapter.kt
@@ -0,0 +1,61 @@
+package com.Apic.apic
+
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.appcompat.widget.AppCompatImageButton
+import androidx.recyclerview.widget.RecyclerView
+
+class DialogAddFriendAdapter(var itemList: ArrayList) : RecyclerView.Adapter() {
+
+ // recyclerview의 chekButton을 위한 함수
+ interface OnAddFriendClickListener {
+ fun onAddFriendClick(position: Int)
+ }
+ private var listener: OnAddFriendClickListener? = null
+ fun setOnAddFriendClickListener(listener: OnAddFriendClickListener) {
+ this.listener = listener
+ }
+ //
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DialogAddFriendAdapter.ViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(R.layout.friend_add_recyclerview, parent, false)
+ return ViewHolder(view)
+ }
+ override fun getItemCount(): Int {
+ return itemList.size
+ }
+ override fun onBindViewHolder(holder: DialogAddFriendAdapter.ViewHolder, position: Int) {
+ Log.d("db", "Adapter1")
+ holder.name.text = itemList[position].name // adapter에 있는 이름에 MemberFriendData의 이름 데이터를 넣는다.
+ holder.emailId.text = itemList[position].email
+ }
+
+ fun setFriendList(list: ArrayList) {
+ itemList = list
+ notifyDataSetChanged()
+ //Log.d("db", "notifyDataSetChanged called")
+ }
+
+ // inner 추가
+ inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
+ val name: TextView = itemView.findViewById(R.id.name)
+ val emailId: TextView = itemView.findViewById(R.id.emailId)
+
+
+ // add : recyclerview의 checkBtn눌렀을 때 반응
+ val checkButton: AppCompatImageButton = itemView.findViewById(R.id.checkButton)
+ init {
+ checkButton?.setOnClickListener {
+ // 반응
+ listener?.onAddFriendClick(adapterPosition)
+ }
+ }
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/DialogFriendAdapter.kt b/app/src/main/java/com/Apic/apic/DialogFriendAdapter.kt
new file mode 100644
index 0000000..010d0c8
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/DialogFriendAdapter.kt
@@ -0,0 +1,48 @@
+package com.Apic.apic
+
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.annotation.NonNull
+import androidx.recyclerview.widget.RecyclerView
+
+class DialogFriendAdapter(var itemList: ArrayList) : RecyclerView.Adapter() {
+
+ private var mFriendList: ArrayList = ArrayList()
+
+ @NonNull
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(R.layout.friend_recyclerview, parent, false)
+ return ViewHolder(view)
+ }
+
+ override fun getItemCount(): Int {
+ return itemList.size
+ }
+
+ // Item을 하나, 하나 보여주는(bind 되는) 함수입니다.
+ override fun onBindViewHolder(holder: DialogFriendAdapter.ViewHolder, position: Int) {
+ Log.d("db", "Adapter1")
+ holder.name.text = itemList[position].name // adapter에 있는 이름에 MemberFriendData의 이름 데이터를 넣는다.
+ holder.emailId.text = itemList[position].email
+ }
+
+
+ fun setFriendList(list: ArrayList) {
+ mFriendList = list
+ itemList = mFriendList
+ for (m in mFriendList) { // 확인용 코드
+ val mname = m.name
+ Log.d("db", mname)
+ }
+ notifyDataSetChanged()
+ //Log.d("db", "notifyDataSetChanged called")
+ }
+
+ inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
+ val name: TextView = itemView.findViewById(R.id.name)
+ val emailId: TextView = itemView.findViewById(R.id.emailId)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/FirebaseData.kt b/app/src/main/java/com/Apic/apic/FirebaseData.kt
index 6ba69de..f8dce64 100644
--- a/app/src/main/java/com/Apic/apic/FirebaseData.kt
+++ b/app/src/main/java/com/Apic/apic/FirebaseData.kt
@@ -2,8 +2,7 @@ package com.Apic.apic
data class FirebaseData(
val Num : Int,
- val name : String,
+ val Name : String,
val Email : String,
val Password : String
-)
-
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/FirstFragment.kt b/app/src/main/java/com/Apic/apic/FirstFragment.kt
deleted file mode 100644
index 79afec4..0000000
--- a/app/src/main/java/com/Apic/apic/FirstFragment.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.Apic.apic
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-
-// TODO: Rename parameter arguments, choose names that match
-// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
-private const val ARG_PARAM1 = "param1"
-private const val ARG_PARAM2 = "param2"
-
-/**
- * A simple [Fragment] subclass.
- * Use the [FirstFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
-class FirstFragment : Fragment() {
- // TODO: Rename and change types of parameters
- private var param1: String? = null
- private var param2: String? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- arguments?.let {
- param1 = it.getString(ARG_PARAM1)
- param2 = it.getString(ARG_PARAM2)
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.fragment_first, container, false)
- }
-
- companion object {
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment BoardFragment.
- */
- // TODO: Rename and change types and number of parameters
- @JvmStatic
- fun newInstance(param1: String, param2: String) =
- FirstFragment().apply {
- arguments = Bundle().apply {
- putString(ARG_PARAM1, param1)
- putString(ARG_PARAM2, param2)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/FourcutFragment.kt b/app/src/main/java/com/Apic/apic/FourcutFragment.kt
new file mode 100644
index 0000000..ed5f678
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/FourcutFragment.kt
@@ -0,0 +1,415 @@
+package com.Apic.apic
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Canvas
+import android.graphics.drawable.BitmapDrawable
+import android.net.Uri
+import android.os.Bundle
+import android.os.Environment
+import android.provider.MediaStore
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.MutableLiveData
+import com.Apic.apic.databinding.FragmentFourcutBinding
+import org.opencv.android.Utils
+import org.opencv.core.Core
+import org.opencv.core.Mat
+import org.opencv.core.Size
+import org.opencv.imgproc.Imgproc
+import org.opencv.photo.Photo.pencilSketch
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.InputStream
+import java.text.SimpleDateFormat
+import java.util.*
+
+/*
+import android.provider.MediaStore
+import androidx.activity.result.contract.ActivityResultContracts
+import com.example.my12application.databinding.ActivityAddBinding
+ */
+
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [FourcutFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+
+class FourcutFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ //뷰에 나타낼 값들. 라이브데이터 형식 (사진 저장)
+ var image = MutableLiveData()
+ var background = MutableLiveData()
+ val content = MutableLiveData()
+
+ lateinit var binding : FourcutFragment
+ private lateinit var targetView: View
+
+ lateinit var originImg: Bitmap
+ init {
+ System.loadLibrary("opencv_java4")
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ var binding = FragmentFourcutBinding.inflate(inflater, container, false)
+
+ // 프레임 색 변경
+ // 주황 버튼
+ binding.btnChangeFrameOrange.setOnClickListener {
+ binding.fourcutFrame.setImageResource(R.drawable.fourcut_orange_img)
+ }
+
+ // 초록 버튼
+ binding.btnChangeFrameGreen.setOnClickListener {
+ binding.fourcutFrame.setImageResource(R.drawable.fourcut_green_img)
+ }
+
+ // 파랑 버튼
+ binding.btnChangeFrameBlue.setOnClickListener {
+ binding.fourcutFrame.setImageResource(R.drawable.fourcut_blue_img)
+ }
+
+ // 사진 불러오기
+ val requestGalleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
+ try{
+ val calRatio = calculateInSampleSize(it.data!!.data!!, resources.getDimensionPixelSize(R.dimen.imgSize), resources.getDimensionPixelSize(R.dimen.imgSize) )
+ val option = BitmapFactory.Options()
+ option.inSampleSize = calRatio
+ var inputStream = context?.contentResolver?.openInputStream(it.data!!.data!!)
+ val bitmap = BitmapFactory.decodeStream(inputStream, null, option)
+ inputStream!!.close() // .close()로 파일을 종료(해주는 습관 필요)
+ inputStream = null
+ // 여기까지가 읽어오는 작업
+
+ bitmap?.let {
+ binding.fourcutFrame.setImageBitmap(bitmap)
+ } ?: let{ Log.d("mobileApp", "bitmap NULL")}
+ } catch (e:Exception) { e.printStackTrace() }
+ }
+
+ binding.btn4cutphoto.setOnClickListener {
+ // 사진 가져오기
+ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) // intent 변수에 Intent() 호출해서 사진 하나를 가져오기 위해서 ACTION_PICK 사용, MediaStore를 통해서 uri를 가져오기
+ // val intent = Intent(Intent.ACTION_PICK)
+ intent.type = "image/*" // 가져오기 전에 가져올 타입을 image만 가져오도록 타입을 지정
+ requestGalleryLauncher.launch(intent)
+ }
+
+ // 버튼 1) 그레이 사진 효과 적용
+ binding.btnChangeEffect1.setOnClickListener {
+
+// val assetManager = resources.assets
+// val inputStream: InputStream = assetManager.open("iv_fourcut_test_img.jpg")
+// val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
+
+ // 불러온 원본 이미지 delete 기능을 위해 저장 (첫 프레임으로 돌아감 -> 추후 수정 예정)
+ if (binding.fourcutFrame.drawable is BitmapDrawable) {
+ originImg = (binding.fourcutFrame.drawable as BitmapDrawable).bitmap
+ } else {
+ val drawable = binding.fourcutFrame.drawable
+ originImg = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+
+ lateinit var bitmap : Bitmap
+
+ if (binding.fourcutFrame.drawable is BitmapDrawable) {
+ bitmap = (binding.fourcutFrame.drawable as BitmapDrawable).bitmap
+ } else {
+ val drawable = binding.fourcutFrame.drawable
+ bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+ val gray = Mat()
+ Utils.bitmapToMat(bitmap, gray)
+
+ Imgproc.cvtColor(gray, gray, Imgproc.COLOR_RGBA2GRAY)
+
+ val grayBitmap = Bitmap.createBitmap(gray.cols(), gray.rows(), Bitmap.Config.ARGB_8888)
+ Utils.matToBitmap(gray, grayBitmap)
+
+ binding.fourcutFrame.setImageBitmap(grayBitmap)
+ Log.d("4cut", "그레이 이미지 설정 완료")
+ }
+
+ binding.btnChangeEffect2.setOnClickListener {
+ // 불러온 원본 이미지 delete 기능을 위해 저장 (첫 프레임으로 돌아감 -> 추후 수정 예정)
+ if (binding.fourcutFrame.drawable is BitmapDrawable) {
+ originImg = (binding.fourcutFrame.drawable as BitmapDrawable).bitmap
+ } else {
+ val drawable = binding.fourcutFrame.drawable
+ originImg = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+
+ val assetManager = resources.assets
+ val inputStream: InputStream = assetManager.open("iv_fourcut_test_img.jpg")
+ // decode 비트맵 변수
+ val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
+
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+ // 비트맵 to mat할 Mat 변수
+ val gray = Mat()
+ Utils.bitmapToMat(bitmap, gray)
+ Log.d("4cut", "1) bitmap to mat 성공")
+
+ Imgproc.cvtColor(gray, gray, Imgproc.COLOR_BGRA2BGR)
+ Log.d("4cut", "Imgproc.COLOR_BGRA2BGR 성공")
+
+ var cartoon = cartoon(gray)
+ Log.d("4cut", "카툰 효과 처리 성공")
+
+ val grayBitmap = Bitmap.createBitmap(gray.cols(), gray.rows(), Bitmap.Config.ARGB_8888)
+ Utils.matToBitmap(cartoon, grayBitmap)
+ // Utils.matToBitmap(cartoon, bitmap)
+
+ binding.fourcutFrame.setImageBitmap(grayBitmap)
+ Log.d("4cut", "카툰 효과 이미지 설정 완료")
+ }
+
+ // 3번째 버튼 : 스케치
+ binding.btnChangeEffect3.setOnClickListener {
+ // 불러온 원본 이미지 delete 기능을 위해 저장 (첫 프레임으로 돌아감 -> 추후 수정 예정)
+ if (binding.fourcutFrame.drawable is BitmapDrawable) {
+ originImg = (binding.fourcutFrame.drawable as BitmapDrawable).bitmap
+ } else {
+ val drawable = binding.fourcutFrame.drawable
+ originImg = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+
+ val assetManager = resources.assets
+ val inputStream: InputStream = assetManager.open("iv_fourcut_test_img.jpg")
+ // decode 비트맵 변수
+ val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+ // 비트맵 to mat할 Mat 변수
+ val gray = Mat()
+
+ Utils.bitmapToMat(bitmap, gray)
+ Log.d("4cut", "1) bitmap to mat 성공")
+
+ Imgproc.cvtColor(gray, gray, Imgproc.COLOR_BGRA2BGR)
+ Log.d("4cut", "Imgproc.COLOR_BGRA2BGR 성공")
+
+ var sketch = Mat()
+ sketch = sketch(gray)
+ Log.d("4cut", "그레이 스케치 효과 처리 성공")
+
+ val grayBitmap = Bitmap.createBitmap(gray.cols(), gray.rows(), Bitmap.Config.ARGB_8888)
+ Utils.matToBitmap(sketch, grayBitmap)
+
+ binding.fourcutFrame.setImageBitmap(grayBitmap)
+ Log.d("4cut", "그레이 스케치 효과 이미지 설정 완료")
+ }
+
+ binding.btnChangeEffect4.setOnClickListener {
+ // 불러온 원본 이미지 delete 기능을 위해 저장 (첫 프레임으로 돌아감 -> 추후 수정 예정)
+ if (binding.fourcutFrame.drawable is BitmapDrawable) {
+ originImg = (binding.fourcutFrame.drawable as BitmapDrawable).bitmap
+ } else {
+ val drawable = binding.fourcutFrame.drawable
+ originImg = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+
+ val assetManager = resources.assets
+ val inputStream: InputStream = assetManager.open("iv_fourcut_test_img.jpg")
+ // decode 비트맵 변수
+ val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+ binding.fourcutFrame.setImageBitmap(bitmap)
+
+ // 비트맵 to mat할 Mat 변수
+ val gray = Mat()
+
+ Utils.bitmapToMat(bitmap, gray)
+ Log.d("4cut", "1) bitmap to mat 성공")
+
+ Imgproc.cvtColor(gray, gray, Imgproc.COLOR_BGRA2BGR)
+ Log.d("4cut", "Imgproc.COLOR_BGRA2BGR 성공")
+
+ var sketch = Mat()
+ pencilSketch(gray, sketch, sketch, 60F, 0.07F, 0.02F)
+ Log.d("4cut", "펜슬 스케치 효과 처리 성공")
+
+ Utils.matToBitmap(sketch, bitmap)
+
+ binding.fourcutFrame.setImageBitmap(bitmap)
+ Log.d("4cut", "펜슬 스케치 효과 이미지 설정 완료")
+ }
+
+ // save 버튼 누를 시
+ binding.btn4cutSave.setOnClickListener {
+ // 사진 저장
+ targetView = binding.fourcutFrame
+
+ Log.d("4cut", "targetView 가져오기")
+ viewSave(targetView)
+ Log.d("4cut", "viewSave() 함수 통과")
+ }
+
+ // Delete 버튼 누를 시
+ binding.btn4cutDelete.setOnClickListener {
+ // 초기화
+ binding.fourcutFrame.setImageBitmap(originImg)
+ }
+ return binding.root
+ }
+
+// private fun getFilePath() : String {
+//
+// }
+
+ private fun getViewBitmap(view: View): Bitmap {
+ val bitmap = Bitmap.createBitmap(
+ view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888
+ )
+ val canvas = Canvas(bitmap)
+ view.draw(canvas)
+ return bitmap
+ }
+
+ private fun getSaveFilePathName(): String {
+ val folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString()
+ val fileName = SimpleDateFormat("yyyyMMddHHmmss").format(Date())
+ return "$folder/$fileName.jpg"
+ }
+
+ private fun bitmapFileSave(bitmap: Bitmap, path: String) {
+ val fos: FileOutputStream
+ try{
+ fos = FileOutputStream(File(path))
+ bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos)
+ fos.close()
+ }catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+
+ private fun viewSave(view: View) {
+ val bitmap = getViewBitmap(view)
+ val filePath = getSaveFilePathName()
+ bitmapFileSave(bitmap, filePath)
+ }
+
+
+ fun sketch(src: Mat): Mat {
+ //회색조 이미지 만들기
+ val gray = Mat()
+ Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY)
+ // 회색조 이미지를 블러시키기
+ val blur = Mat()
+ Imgproc.GaussianBlur(gray, blur, Size(0.0, 0.0), 12.0)
+ // 엣지만 남고 평탄한 부분은 흰색으로 바뀜
+ val dst = Mat()
+ Core.divide(gray, blur, dst, 255.0)
+ return dst
+ }
+
+ fun cartoon(src: Mat): Mat {
+ val width = src.width()
+ val height = src.height()
+ // 이미지의 크기를 줄이면 효과적으로 뭉개고, 연산량을 빨리 하는 효과가 있음.
+ val resizedSrc = Mat()
+ Imgproc.resize(src, resizedSrc, Size(width / 8.0, height / 8.0))
+ // 블러 적용
+ val blur = Mat()
+ Imgproc.bilateralFilter(resizedSrc, blur, -1, 20.0, 7.0)
+ // 엣지 검출한 뒤, 이미지를 반전시킨다.
+ val edge = Mat()
+ Imgproc.Canny(resizedSrc, edge, 100.0, 150.0)
+ Core.bitwise_not(edge, edge)
+ Imgproc.cvtColor(edge, edge, Imgproc.COLOR_GRAY2BGR)
+ //블러시킨 이미지와 반전된 edge를 and연산자로 합치면 edge부분은 검정색으로 나오고, 나머지는 많이 뭉개지고 블러처리된 이미지로 나옴, 카툰효과
+ val dst = Mat()
+ Core.bitwise_and(blur, edge, dst)
+ Imgproc.resize(dst, dst, Size(width.toDouble(), height.toDouble()), 1.0, 1.0, Imgproc.INTER_NEAREST)
+ return dst
+ }
+
+
+ // 갤러리에서 사진을 불러오는 것 (+ 불러온 이미지 크기 조정)
+ private fun calculateInSampleSize(fileUri: Uri, reqWidth: Int, reqHeight: Int): Int {
+ val options = BitmapFactory.Options()
+ options.inJustDecodeBounds = true
+ try {
+ var inputStream = context?.contentResolver?.openInputStream(fileUri)
+
+ //inJustDecodeBounds 값을 true 로 설정한 상태에서 decodeXXX() 를 호출.
+ //로딩 하고자 하는 이미지의 각종 정보가 options 에 설정 된다.
+ BitmapFactory.decodeStream(inputStream, null, options)
+ inputStream!!.close()
+ inputStream = null
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //비율 계산........................
+ val (height: Int, width: Int) = options.run { outHeight to outWidth }
+ var inSampleSize = 1
+ //inSampleSize 비율 계산
+ if (height > reqHeight || width > reqWidth) {
+
+ val halfHeight: Int = height / 2
+ val halfWidth: Int = width / 2
+
+ while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
+ inSampleSize *= 2
+ }
+ }
+ return inSampleSize
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment FourcutFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ FourcutFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
+
diff --git a/app/src/main/java/com/Apic/apic/FragmentPagerAdapter.kt b/app/src/main/java/com/Apic/apic/FragmentPagerAdapter.kt
index ec58665..2b684a5 100644
--- a/app/src/main/java/com/Apic/apic/FragmentPagerAdapter.kt
+++ b/app/src/main/java/com/Apic/apic/FragmentPagerAdapter.kt
@@ -16,8 +16,11 @@ class FragmentPagerAdapter (
override fun createFragment(position: Int): Fragment {
return if (position == 0)
- DateFragment()
+ AlbumFragment()
else
MemberFragment()
-}}
\ No newline at end of file
+}
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/FriendData.kt b/app/src/main/java/com/Apic/apic/FriendData.kt
new file mode 100644
index 0000000..64b6fca
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/FriendData.kt
@@ -0,0 +1,6 @@
+package com.Apic.apic
+
+data class FriendData(
+ val f_email: String,
+ val f_name: String
+)
diff --git a/app/src/main/java/com/Apic/apic/FriendFragment.kt b/app/src/main/java/com/Apic/apic/FriendFragment.kt
index 4d0d9bb..4ca67ae 100644
--- a/app/src/main/java/com/Apic/apic/FriendFragment.kt
+++ b/app/src/main/java/com/Apic/apic/FriendFragment.kt
@@ -1,10 +1,23 @@
package com.Apic.apic
+import android.content.Context
import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.EditText
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.Apic.apic.databinding.FragmentFriendBinding
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.firestore.FirebaseFirestore
+
+
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
@@ -13,31 +26,133 @@ class FriendFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
+ private lateinit var mRecyclerView: RecyclerView
+ private lateinit var mRecyclerAdapter: DialogFriendAdapter
+ private lateinit var editText: EditText
+ private val originalList: ArrayList = ArrayList()
+ private val searchList: ArrayList = ArrayList()
+
+ // firestore에서 data가져올때 사용
+ private lateinit var auth: FirebaseAuth // 친구 리스트와 현재 로그인 user email 비교를 위해 가져옴.
+ private val db = FirebaseFirestore.getInstance()
+ private var adapter = DialogFriendAdapter(originalList)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
-
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.fragment_friend, container, false)
+ val binding = FragmentFriendBinding.inflate(inflater, container, false)
+ auth = FirebaseAuth.getInstance()
+
+ mRecyclerView = binding.recyclerView
+
+ // initiate adapter & recyclerview
+ mRecyclerAdapter = DialogFriendAdapter(originalList)
+ mRecyclerView.adapter = mRecyclerAdapter
+ mRecyclerView.layoutManager = LinearLayoutManager(requireContext())
+
+ // 친구 firestore 'memberDB'의 friendlist를 가져옴.
+ // 친구 찾기에서 친구 리스트로 recyclerview로 뜨기
+ db.collection("memberDB")
+ .document(auth.currentUser?.email.toString())
+ .collection("FriendList") // friendlist 항목 넣어야함.
+ .get() // Get documents
+ .addOnSuccessListener { result ->
+ // On success
+ originalList.clear()
+ for (document in result) {
+ val item = MemberData(
+ document["email"] as String,
+ document["name"] as String,
+ )
+ // 현재 유저가 아닐때
+ if (!auth.currentUser?.email.toString().equals(document["email"])) {
+ originalList.add(item)
+ }
+ }
+
+ // 데이터 로드가 완료된 후에 어댑터 초기화와 업데이트
+ adapter.notifyDataSetChanged()
+ }
+ .addOnFailureListener { exception ->
+ Log.w("AddFriendFragment", "Error getting documents: $exception")
+ }
+
+ mRecyclerAdapter.setFriendList(originalList)
+
+ // Button click listener : AddFriendFragment로 이동
+ binding.addButton.setOnClickListener {
+ (activity as? MainActivity)?.setFragment(1)
+ }
+
+ // Button click listener : search Friend email
+ binding.searchButton.setOnClickListener{
+ val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.hideSoftInputFromWindow(binding.searchView.windowToken, 0)
+ }
+
+ editText = binding.searchView // 검색어 변수로 받음.
+
+ editText.addTextChangedListener(object : TextWatcher {
+ override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
+ // Optional: Add any functionality needed before text changes
+ }
+ override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
+ // Optional: Add any functionality needed during text changes
+ }
+
+ override fun afterTextChanged(editable: Editable) {
+ //Log.d("db", "addTextChangedListener")
+ val searchText = editText.text.toString().trim() // trim()추가 : 검색 편리화, 띄어쓰기해도 검색 가능
+ //Log.d("db", "$searchText")
+ searchList.clear() // 검색 결과 갱신
+
+ if (searchText.isEmpty()) {
+ adapter.setFriendList(originalList)
+ } else {
+ // 검색 단어를 포함하는지 확인
+ for (a in 0 until originalList.size) {
+ //Log.d("db", "for loop: $a")
+ if (originalList[a].getName().toLowerCase().contains(searchText.toLowerCase(), ignoreCase=true)) { // ignoreCase=true : 검색 편리화, 대문자=소문자
+ searchList.add(originalList[a])
+ }
+ }
+ /*for (original in originalList){ // for문의 또다른 방식 - 간단해서 추천 삭제해도 됨.
+ if(searchText.contains(original.getName(), ignoreCase=true)){
+ val fname = original.name
+ val femail = original.email
+ Log.d("db", fname)
+ Log.d("db", femail)
+ val search = MemberData(femail. fname)
+ searchList.add(search)
+ }
+ }*/
+ adapter.setFriendList(searchList)
+ adapter.notifyDataSetChanged()
+ }
+ }
+ })
+
+ // 리사이클러뷰, 어댑터 연결
+ val recyclerView: RecyclerView = binding.recyclerView
+ recyclerView.layoutManager = LinearLayoutManager(requireContext())
+
+ //어댑터 연결 확인
+ //adapter = DialogFriendAdapter(originalList)
+ adapter.setFriendList(originalList)
+ recyclerView.adapter = adapter
+ return binding.root
}
+
companion object {
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment FriendFragment.
- */
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
diff --git a/app/src/main/java/com/Apic/apic/FriendList.kt b/app/src/main/java/com/Apic/apic/FriendList.kt
new file mode 100644
index 0000000..8f6cb33
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/FriendList.kt
@@ -0,0 +1,11 @@
+package com.Apic.apic
+
+class FriendList (
+ val email : String,
+ val name : String
+){
+ @JvmName("callFromString")
+ fun getName(): String {
+ return name
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/GroupActivity.kt b/app/src/main/java/com/Apic/apic/GroupActivity.kt
index 1a41e39..bddaebf 100644
--- a/app/src/main/java/com/Apic/apic/GroupActivity.kt
+++ b/app/src/main/java/com/Apic/apic/GroupActivity.kt
@@ -1,42 +1,57 @@
package com.Apic.apic
import android.animation.ObjectAnimator
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
import android.view.View
-import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.PopupMenu
+import android.widget.TextView
import android.widget.Toast
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.FragmentTransaction
import androidx.viewpager2.widget.ViewPager2
+import com.Apic.apic.databinding.ActivityGroupBinding
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.tabs.TabLayout
class GroupActivity : AppCompatActivity() {
+ // 뷰 변수 선언
private lateinit var tabLayout: TabLayout
private lateinit var viewPager2: ViewPager2
private lateinit var adapter: FragmentPagerAdapter
- private var isFabOpen = false
-
+ private lateinit var albumAdapter: AlbumAdapter
private lateinit var fabMain: FloatingActionButton
private lateinit var fabCamera: FloatingActionButton
private lateinit var fabCreate: FloatingActionButton
private lateinit var groupLikedButton: ImageButton
- private var isLiked = false
- private val fragmentAddMeeting = AddMeetingFragment()
+
private lateinit var menuIcon: ImageButton
+ lateinit var binding: ActivityGroupBinding
+
+ // 상태 변수 선언
+ private var isFabOpen = false
+ private var isLiked = false
+ var imageList: ArrayList = ArrayList()
private val fragmentManager: FragmentManager = supportFragmentManager
+ private lateinit var groupName: TextView
+ private lateinit var groupMemberNum: TextView
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.acticity_group)
+ // ViewBinding을 사용하여 콘텐츠 뷰 설정
+ binding = ActivityGroupBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ // albumAdapter 초기화
+ albumAdapter = AlbumAdapter(imageList, this)
// 뷰 초기화
initializeViews()
@@ -57,19 +72,34 @@ class GroupActivity : AppCompatActivity() {
fabCreate = findViewById(R.id.fab_create)
groupLikedButton = findViewById(R.id.group_liked)
menuIcon = findViewById(R.id.menu_icon)
+ groupName = findViewById(R.id.group_name)
+ groupMemberNum = findViewById(R.id.group_member_num)
+
+ // 그룹 정보 반영
+ val gName = intent.getStringExtra("g_name")
+ val gParticipants = intent.getStringExtra("g_participants")
+ groupName.text = gName
+ groupMemberNum.text = gParticipants
+
+ // MemberFragment에 그룹 정보 전달
+ var memberFragment = MemberFragment()
+ var bundle = Bundle()
+ bundle.putString("g_name", gName)
+ memberFragment.arguments = bundle
}
// 탭 레이아웃 설정
private fun setupTabLayout() {
adapter = FragmentPagerAdapter(supportFragmentManager, lifecycle)
- tabLayout.addTab(tabLayout.newTab().setText("date"))
+ tabLayout.addTab(tabLayout.newTab().setText("album"))
tabLayout.addTab(tabLayout.newTab().setText("member"))
viewPager2.adapter = adapter
}
- // 뷰페이저 설정
+ // 뷰페이저와 콜백을 설정
private fun setupViewPager() {
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
+ // 탭 선택 이벤트 처리
override fun onTabSelected(tab: TabLayout.Tab?) {
tab?.let { viewPager2.currentItem = it.position }
}
@@ -83,6 +113,7 @@ class GroupActivity : AppCompatActivity() {
}
})
+ // 뷰페이저 페이지 변경 콜백 설정
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
@@ -91,19 +122,33 @@ class GroupActivity : AppCompatActivity() {
})
}
- // 리스너 설정
+ // FAB, 버튼 및 메뉴 아이콘의 클릭 리스너 설정
private fun setupListeners() {
- fabMain.setOnClickListener {
- // toggleFab()
- // viewpager AddMeetingFragment로 전환
-
+ fabMain.setOnClickListener { toggleFab() }
+ fabCamera.setOnClickListener {
+ showToast("카메라 버튼 클릭!")
+
+ // 이미지 선택 액티비티 시작
+ val intent = Intent(Intent.ACTION_PICK)
+ intent.type = "image/*"
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) // 다중 이미지 선택 활성화
+ activityResult.launch(intent)
}
- fabCamera.setOnClickListener { showToast("카메라 버튼 클릭!") }
fabCreate.setOnClickListener { showToast("버튼 클릭!") }
groupLikedButton.setOnClickListener { toggleLikedState() }
menuIcon.setOnClickListener { showPopupMenu(it) }
}
+ // 이미지 선택 액티비티 결과 처리
+ private val activityResult: ActivityResultLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK && result.data != null) {
+ // 선택한 이미지를 가져와 현재 프래그먼트의 이미지 목록 업데이트
+ val albumFragment = supportFragmentManager.findFragmentByTag("f${viewPager2.currentItem}") as? AlbumFragment
+ albumFragment?.updateImageList(result.data)
+ }
+ }
+
// 플로팅 버튼 토글
private fun toggleFab() {
showToast("메인 플로팅 버튼 클릭!")
@@ -111,22 +156,21 @@ class GroupActivity : AppCompatActivity() {
val translateYCamera = if (isFabOpen) 0f else -200f
val translateYCreate = if (isFabOpen) 0f else -400f
+ // FAB 애니메이션
ObjectAnimator.ofFloat(fabCamera, "translationY", translateYCamera).start()
ObjectAnimator.ofFloat(fabCreate, "translationY", translateYCreate).start()
+ // 메인 FAB 아이콘 변경 및 열린 상태 업데이트
fabMain.setImageResource(R.drawable.ic_add)
isFabOpen = !isFabOpen
}
// 즐겨찾기 상태 토글
private fun toggleLikedState() {
-
isLiked = !isLiked
-
// 즐겨찾기 상태에 따라 아이콘 변경
groupLikedButton.setImageResource(if (isLiked) R.drawable.ic_liked else R.drawable.ic_unliked)
-
- // 즐겨찾기 상태에 따라 토스트 메시지 출력
+ // 즐겨찾기 상태에 따라 토스트 메세지 출력
showToast(if (isLiked) "즐겨찾기 등록!" else "즐겨찾기 해제!")
}
@@ -136,6 +180,7 @@ class GroupActivity : AppCompatActivity() {
val inflater = popupMenu.menuInflater
inflater.inflate(R.menu.menu_group, popupMenu.menu)
+ // 메뉴 아이템 클릭 처리
popupMenu.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.menu_item1 -> {
@@ -146,7 +191,8 @@ class GroupActivity : AppCompatActivity() {
R.id.menu_item2 -> {
showToast("메뉴 아이템 2 클릭!")
true
- }// 추가적인 메뉴 아이템이 필요한 경우 여기에 추가
+ }
+ // 추가적인 메뉴 아이템 필요한 경우 여기에 추가
else -> false
}
}
diff --git a/app/src/main/java/com/Apic/apic/GroupData.kt b/app/src/main/java/com/Apic/apic/GroupData.kt
new file mode 100644
index 0000000..eacc729
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/GroupData.kt
@@ -0,0 +1,9 @@
+package com.Apic.apic
+
+data class GroupData (
+ val g_name : String = "",
+ val g_participants : String
+ )
+
+
+
diff --git a/app/src/main/java/com/Apic/apic/GroupDateAdapter.kt b/app/src/main/java/com/Apic/apic/GroupDateAdapter.kt
index 05d2dcb..1091c26 100644
--- a/app/src/main/java/com/Apic/apic/GroupDateAdapter.kt
+++ b/app/src/main/java/com/Apic/apic/GroupDateAdapter.kt
@@ -3,8 +3,6 @@ package com.Apic.apic
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.TextView
-import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.Apic.apic.databinding.RvGroupDateBinding
diff --git a/app/src/main/java/com/Apic/apic/GroupListAdapter.kt b/app/src/main/java/com/Apic/apic/GroupListAdapter.kt
index ae5fcff..e05f4c7 100644
--- a/app/src/main/java/com/Apic/apic/GroupListAdapter.kt
+++ b/app/src/main/java/com/Apic/apic/GroupListAdapter.kt
@@ -1,27 +1,20 @@
package com.Apic.apic
-import android.content.Context
-import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.Toast
-import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.RecyclerView
import com.Apic.apic.databinding.RvGroupListBinding
-class GroupListAdapter : RecyclerView.Adapter() {
+class GroupListAdapter(var items:MutableList) : RecyclerView.Adapter() {
private lateinit var itemClickListener : OnItemClickListener
- private var data = ArrayList()
+
+ private var mGroupList: MutableList = ArrayList()
inner class ViewHolder(val binding: RvGroupListBinding): RecyclerView.ViewHolder(binding.root) {
- fun onBind(item: GroupListItem) {
- binding.groupName.text = item.getGroupName() // 그룹 이름
- binding.groupNum.text = item.getGroupNum().toString() // 그룹 멤버명수
- binding.groupLiked.isActivated = item.isGroupLiked() // 그룹 즐겨찾기 (안됨)
-// Glide.with(binding) // 그룹 사진
-// .load(item.group_photo)
-// .into(binding.groupPhoto)
+ fun onBind(items: GroupData) {
+ binding.groupName.text = items.g_name // 그룹 이름
+ binding.groupNum.text = items.g_participants // 그룹 멤버명수
}
}
// 아이템 클릭리스너
@@ -41,23 +34,20 @@ class GroupListAdapter : RecyclerView.Adapter() {
}
override fun getItemCount(): Int {
- return data.size
+ return items.size
}
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- holder.onBind(data[position])
+ override fun onBindViewHolder(holder: GroupListAdapter.ViewHolder, position: Int) {
+ holder.onBind(items[position])
holder.itemView.setOnClickListener {
itemClickListener.onClick(it, position)
}
}
- fun replaceList(newList: ArrayList) {
- data = newList
- // 어댑터에 데이터가 변했다는 notify를 날린다
+ fun setGroupList(list: MutableList) {
+ mGroupList = list
+ items = mGroupList
notifyDataSetChanged()
}
-
-
-
}
diff --git a/app/src/main/java/com/Apic/apic/GroupListFragment.kt b/app/src/main/java/com/Apic/apic/GroupListFragment.kt
index 65215f1..c252529 100644
--- a/app/src/main/java/com/Apic/apic/GroupListFragment.kt
+++ b/app/src/main/java/com/Apic/apic/GroupListFragment.kt
@@ -2,15 +2,18 @@ package com.Apic.apic
import android.content.Intent
import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.Log
import android.view.*
+import android.widget.EditText
import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.Apic.apic.databinding.FragmentAddGroupBinding
import com.Apic.apic.databinding.FragmentGroupListBinding
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.firestore.FirebaseFirestore
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@@ -27,16 +30,34 @@ class GroupListFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
- private val group_datas : ArrayList = ArrayList()
+ private val groupList = mutableListOf()
private lateinit var groupListAdapter: GroupListAdapter
+ private val searchList: ArrayList = ArrayList()
+ private lateinit var Etsearch: EditText
+
+ private lateinit var auth: FirebaseAuth
+ private val db = FirebaseFirestore.getInstance()
+
+
private fun setOnClickEvent() {
- groupListAdapter.setItemClickListener(object:GroupListAdapter.OnItemClickListener {
+ groupListAdapter.setItemClickListener(object: GroupListAdapter.OnItemClickListener {
override fun onClick(view:View, position:Int) {
super.onClick(view, position)
- Toast.makeText(view.context, "테스트 - ${group_datas[position].getGroupName()}클릭", Toast.LENGTH_SHORT).show()
- val intent = Intent(getActivity(), GroupActivity::class.java)
+ Toast.makeText(view.context, "테스트 - ${groupList[position].g_name}클릭", Toast.LENGTH_SHORT).show()
+
+ // 그룹 정보 넘기기 -> groupActivity
+ val intent = Intent(activity, GroupActivity::class.java)
+ intent.putExtra("g_name", groupList[position].g_name)
+ intent.putExtra("g_participants", groupList[position].g_participants)
startActivity(intent)
+
+ // 그룹 정보 넘기기 -> memberFragment
+ var memberFragment = MemberFragment()
+ var bundle = Bundle()
+ bundle.putString("g_name", groupList[position].g_name)
+ Log.d("groupname", bundle.toString())
+ memberFragment.arguments = bundle
}
})
}
@@ -55,15 +76,11 @@ class GroupListFragment : Fragment() {
// Inflate the layout for this fragment
val binding = FragmentGroupListBinding.inflate(inflater, container, false)
- group_datas.add(GroupListItem("GroupA", 3, true))
- group_datas.add(GroupListItem("GroupB", 5, true))
- group_datas.add(GroupListItem("GroupC", 6, true))
- group_datas.add(GroupListItem("GroupD", 9, true))
+ auth = FirebaseAuth.getInstance()
val recyclerView: RecyclerView = binding.groupRecyclerView
recyclerView.layoutManager = LinearLayoutManager(requireContext())
- groupListAdapter = GroupListAdapter()
- groupListAdapter.replaceList(group_datas)
+ groupListAdapter = GroupListAdapter(groupList)
recyclerView.adapter = groupListAdapter
setOnClickEvent()
@@ -74,14 +91,67 @@ class GroupListFragment : Fragment() {
if (transaction != null) {
transaction.replace(R.id.menu_frame_view, AddGroupFragment()).commitAllowingStateLoss()
}
-
}
+ // 그룹 리스트
+ getGroupData()
//(activity as AppCompatActivity).setSupportActionBar(R.id.back) // 뒤로가기 메뉴
+ // 그룹 검색
+ Etsearch = binding.Etsearch
+ Etsearch.addTextChangedListener(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 searchText = Etsearch.text.toString().trim()
+ searchList.clear()
+
+ if (searchText.isEmpty()) {
+ groupListAdapter.setGroupList(groupList)
+ }
+ else {
+ for (a in 0 until groupList.size) {
+ if (groupList[a].g_name.toLowerCase().contains(searchText.toLowerCase())) {
+ searchList.add(groupList[a])
+ }
+ }
+ }
+ groupListAdapter.setGroupList(searchList)
+ groupListAdapter.notifyDataSetChanged()
+ }
+ })
+
return binding.root
}
+ private fun getGroupData() {
+ db.collection("memberDB")
+ .document(auth.currentUser!!.email.toString())
+ .collection("groups")
+ .get()
+ .addOnSuccessListener { result ->
+ groupList.clear()
+ for (document in result) {
+ val group = GroupData (
+ document["g_name"] as String,
+ document["g_participants"] as String
+ )
+ groupList.add(group)
+ }
+ groupListAdapter.notifyDataSetChanged()
+ Log.d("db", "success")
+ }
+ .addOnFailureListener {
+ Log.d("db", "fail")
+ }
+ }
+
// 뒤로가기 버튼
// override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
// inflater.inflate(R.menu.toolbar_menu, menu)
diff --git a/app/src/main/java/com/Apic/apic/GroupListItem.kt b/app/src/main/java/com/Apic/apic/GroupListItem.kt
deleted file mode 100644
index 0a4deab..0000000
--- a/app/src/main/java/com/Apic/apic/GroupListItem.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.Apic.apic
-
-data class GroupListItem(
-// val group_photo : String = "", // 그룹 사진
- val group_name: String = "", // 그룹 이름
- val group_num: Int = 0, // 그룹 멤버명수
- val group_liked : Boolean = false // 그룹 즐겨찾기
-)
-{
- fun getGroupName(): String {
- return group_name
- }
- fun getGroupNum() : Int {
- return group_num
- }
- fun isGroupLiked() : Boolean {
- return group_liked
- }
- }
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/GroupMemberAdapter.kt b/app/src/main/java/com/Apic/apic/GroupMemberAdapter.kt
index afb85be..4c8ab7d 100644
--- a/app/src/main/java/com/Apic/apic/GroupMemberAdapter.kt
+++ b/app/src/main/java/com/Apic/apic/GroupMemberAdapter.kt
@@ -5,12 +5,11 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.Apic.apic.databinding.RvGroupMemberBinding
-class GroupMemberAdapter: RecyclerView.Adapter() {
- private var data = ArrayList()
+class GroupMemberAdapter(val items:MutableList): RecyclerView.Adapter() {
inner class ViewHolder(val binding: RvGroupMemberBinding): RecyclerView.ViewHolder(binding.root) {
- fun onBind(item : String) {
- binding.memberName.text = item
+ fun onBind(items : GroupMemberData) {
+ binding.memberName.text = items.gm_name
}
}
@@ -20,17 +19,12 @@ class GroupMemberAdapter: RecyclerView.Adapter()
return ViewHolder(binding)
}
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- holder.onBind(data[position])
+ override fun onBindViewHolder(holder: GroupMemberAdapter.ViewHolder, position: Int) {
+ holder.onBind(items[position])
}
override fun getItemCount(): Int {
- return data.size
+ return items.size
}
- fun replaceList(newList:ArrayList) {
- data = newList
- // 어댑터에 데이터가 변했다는 notify를 날린다
- notifyDataSetChanged()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/GroupMemberData.kt b/app/src/main/java/com/Apic/apic/GroupMemberData.kt
new file mode 100644
index 0000000..23f9219
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/GroupMemberData.kt
@@ -0,0 +1,5 @@
+package com.Apic.apic
+
+data class GroupMemberData (
+ val gm_name:String
+)
diff --git a/app/src/main/java/com/Apic/apic/GroupParticipantsAdapter.kt b/app/src/main/java/com/Apic/apic/GroupParticipantsAdapter.kt
new file mode 100644
index 0000000..0f964d3
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/GroupParticipantsAdapter.kt
@@ -0,0 +1,45 @@
+package com.Apic.apic
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.Apic.apic.databinding.RvGroupParticipantsBinding
+
+class GroupParticipantsAdapter(val items:MutableList) : RecyclerView.Adapter() {
+ private lateinit var itemClickListener : OnItemClickListener
+
+ inner class ViewHolder(val binding: RvGroupParticipantsBinding): RecyclerView.ViewHolder(binding.root) {
+ fun onBind(items : FriendData) {
+ binding.memberName.text = items.f_name
+ binding.memberId.text = items.f_email
+ }
+ }
+
+ interface OnItemClickListener {
+ fun onClick(view: View, position: Int) {
+ // Toast.makeText(view.context, "테스트 - ${position}클릭", Toast.LENGTH_SHORT).show()
+ }
+ }
+ fun setItemClickListener(onItemClickListener: OnItemClickListener) {
+ this.itemClickListener = onItemClickListener
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ var layoutInflater = LayoutInflater.from(parent.context)
+ val binding = RvGroupParticipantsBinding.inflate(layoutInflater,parent,false)
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: GroupParticipantsAdapter.ViewHolder, position: Int) {
+ holder.onBind(items[position])
+ holder.itemView.setOnClickListener {
+ itemClickListener.onClick(it, position)
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return items.size
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/LoginActivity.kt b/app/src/main/java/com/Apic/apic/LoginActivity.kt
index 98b92a2..23a83f6 100644
--- a/app/src/main/java/com/Apic/apic/LoginActivity.kt
+++ b/app/src/main/java/com/Apic/apic/LoginActivity.kt
@@ -4,26 +4,18 @@ import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
-import android.view.View
import android.widget.Button
import android.widget.EditText
-import android.widget.ImageView
-import android.widget.TextView
import android.widget.Toast
-import androidx.core.content.ContextCompat.startActivity
-import androidx.core.view.isVisible
-import com.Apic.apic.databinding.ActivityLoginBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
-import java.util.jar.Attributes
+import com.Apic.apic.databinding.ActivityLoginBinding
class LoginActivity : AppCompatActivity() {
- lateinit var registerBinding: ActivityLoginBinding
- private var _binding: ActivityLoginBinding?= null
- private val binding get() =_binding!!
+ private lateinit var binding: ActivityLoginBinding
- lateinit var nameEt : EditText //이름
+ lateinit var nameEt: EditText //이름
lateinit var emailEt: EditText //이메일
lateinit var passwordEt: EditText //pw
lateinit var loginBtn: Button
@@ -35,7 +27,7 @@ class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- _binding = ActivityLoginBinding.inflate(layoutInflater)
+ binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
//topbar에 있는 회원페이지 안 보이게 하기 (사실상 로그인 페이지에 더이상 topbar가 필요 없어서 topbar자체를 삭제)
@@ -50,15 +42,16 @@ class LoginActivity : AppCompatActivity() {
nameEt = findViewById(R.id.user_name)
emailEt = findViewById(R.id.user_id)
+ // 로그인
passwordEt = findViewById(R.id.user_pw)
loginBtn = findViewById(R.id.button)
- //로그인
loginBtn.setOnClickListener {
var email = emailEt.text.toString()
var password = passwordEt.text.toString()
var name = nameEt.text.toString()
+
auth.createUserWithEmailAndPassword(email, password) // 회원 가입
.addOnCompleteListener(this) { result ->
if (result.isSuccessful) {
@@ -69,6 +62,9 @@ class LoginActivity : AppCompatActivity() {
//data를 firebase에 저장
val data = FirebaseData(sampleNumber, name, email, password)
setDocument(data) // 데이터 Firestore에 저장
+ // val memberData = MemberData(email, name, password)
+ val memberData = MemberData(email, name)
+ setMember(memberData)
var intent = Intent(this, MainActivity::class.java)
intent.putExtra("name", name) //name도 함께 전달
startActivity(intent)
@@ -85,16 +81,35 @@ class LoginActivity : AppCompatActivity() {
}
fun login(email:String,password:String){
+ nameEt = findViewById(R.id.user_name)
+ var name = nameEt.text.toString()
+
auth.signInWithEmailAndPassword(email,password) // 로그인
.addOnCompleteListener {
result->
if(result.isSuccessful){
var intent = Intent(this, MainActivity::class.java)
+ intent.putExtra("name", name) //name도 함께 전달
startActivity(intent)
}
}
}
+
+ // Firestore의 memberDB에 데이터 저장 함수
+ private fun setMember(data : MemberData){
+ Log.d("db", "firebaseStore")
+ val db = FirebaseFirestore.getInstance()
+ db.collection("memberDB")
+ .document(data.email)
+ .set(data)
+ .addOnSuccessListener {
+ Log.d("db", "success")
+ }.addOnFailureListener{
+ Log.d("db", "fail")
+ }
+ }
+
// Firestore에 데이터를 저장하는 함수
private fun setDocument(data: FirebaseData) {
Log.d("DB", "firebaseStore")
diff --git a/app/src/main/java/com/Apic/apic/MainActivity.kt b/app/src/main/java/com/Apic/apic/MainActivity.kt
index 0945f1c..865dd75 100644
--- a/app/src/main/java/com/Apic/apic/MainActivity.kt
+++ b/app/src/main/java/com/Apic/apic/MainActivity.kt
@@ -1,47 +1,40 @@
package com.Apic.apic
-
+import android.app.Activity
import android.content.Intent
+import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
-import android.os.PersistableBundle
import android.util.Log
-import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
-import android.view.Window
-import android.widget.Button
-import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
-import android.widget.Toolbar
-import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.Apic.apic.databinding.ActivityMainBinding
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
-import com.Apic.apic.databinding.TopbarBinding
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.navigation.NavigationView
-import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener
import com.google.firebase.auth.FirebaseAuth
-import com.google.firebase.firestore.DocumentReference
-import com.google.firebase.firestore.FirebaseFirestore
-import org.w3c.dom.Text
-import kotlin.math.log
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
lateinit var binding: ActivityMainBinding
- private val fragmentManager: FragmentManager = supportFragmentManager
+ private lateinit var fragmentTransaction: FragmentTransaction //
+ private val fragmentAddFriend = AddFriendFragment()
+ private var fragmentManager: FragmentManager = supportFragmentManager
private val fragmentCalendar = CalendarFragment()
private val fragmentFriend = FriendFragment()
private val fragmentGroupList = GroupListFragment()
+ private val fragmentFourcut = FourcutFragment()
private lateinit var auth: FirebaseAuth
- var MenuAuth : MenuItem ?= null
+ companion object {
+ const val PICK_IMAGE_REQUEST_CODE = 1000 // 아무 숫자나 상관없지만 중복되지 않도록 정의
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -49,12 +42,9 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
setContentView(binding.root)
auth = FirebaseAuth.getInstance()
-// email = findViewById(R.id.userEmail)
-// email.text = auth.currentUser?.email // 회원 이메일 표시
val transaction: FragmentTransaction = fragmentManager.beginTransaction()
- transaction.replace(R.id.menu_frame_view, fragmentCalendar).commitAllowingStateLoss()
-
+ transaction.replace(R.id.menu_frame_view,fragmentCalendar).commitAllowingStateLoss()
//Login// -> menu_nav로 옮겨서 아래 Item에 있어요
@@ -83,11 +73,13 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
.commitAllowingStateLoss()
R.id.menu_share -> transaction.replace(R.id.menu_frame_view, fragmentGroupList)
.commitAllowingStateLoss()
-
+ R.id.menu_fourcut -> transaction.replace(R.id.menu_frame_view, fragmentFourcut)
+ .commitAllowingStateLoss()
}
true
}
+
//drawer-> navigation_hear에 있는 textView에 현재 로그인 정보 전달
val navigationView: NavigationView = findViewById(R.id.main_drawer)
navigationView.setNavigationItemSelectedListener(this)
@@ -98,7 +90,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
val auth_email: TextView = headerView.findViewById(R.id.auth_email)
//firebaseAuth 데이터 가져오기
val user = auth.currentUser
- val db = FirebaseFirestore.getInstance()
user?.let { currentUser ->
user?.let {
@@ -130,31 +121,63 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
}
- override fun onNavigationItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- R.id.logOut -> {
- Log.d("logout", "로그아웃 버튼 클릭")
-
- auth.signOut()
- val intent = Intent(this, LoginActivity::class.java)
- startActivity(intent)
- finish()
- true
- }
- else -> super.onOptionsItemSelected(item)
+ override fun onNavigationItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.galleryButton -> {
+ Log.d("item", "사진 불러오기")
+
+ val intent = Intent(Intent.ACTION_PICK)
+ intent.type = "image/*"
+ startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)
+
+ true
+ }
+ R.id.logOut -> {
+ Log.d("logout", "로그아웃 버튼 클릭")
+
+ auth.signOut()
+ val intent = Intent(this, LoginActivity::class.java)
+ startActivity(intent)
+ finish()
+ true
}
- }
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
//옵션메뉴 -> 메뉴바 보여지도록 가시화(명시)
//옵션 멘 만들기
- override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.menu_navigation, menu)
- return super.onCreateOptionsMenu(menu)
- }
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.menu_navigation, menu)
+ return super.onCreateOptionsMenu(menu)
+ }
-}
+ fun setFragment(n: Int) {
+ fragmentManager = supportFragmentManager
+ fragmentTransaction = fragmentManager.beginTransaction()
+ when (n) {
+ 1 -> fragmentTransaction.replace(R.id.menu_frame_view, fragmentAddFriend).commit() // FriendFragment, addButton눌렀을 때
+ }
+ when (n) {
+ 0 -> fragmentTransaction.replace(R.id.menu_frame_view, fragmentFriend).commit() // FriendFragment, addButton눌렀을 때
+ }
+
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == PICK_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
+ if (data != null) {
+ val selectedImageUri: Uri? = data.data
+ // 선택한 이미지 URI를 auth_img에 설정
+ val auth_img: ImageView = findViewById(R.id.userImageView)
+ auth_img.setImageURI(selectedImageUri)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/MainViewModel.kt b/app/src/main/java/com/Apic/apic/MainViewModel.kt
new file mode 100644
index 0000000..8a5d88d
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/MainViewModel.kt
@@ -0,0 +1,61 @@
+// MainViewModel.kt
+package com.Apic.apic
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import androidx.room.Room
+import com.Apic.apic.data.Todo
+import com.Apic.apic.data.TodoDatabase
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+class MainViewModel(application: Application) : AndroidViewModel(application) {
+ // 데이터베이스
+ private val db = Room.databaseBuilder(
+ application,
+ TodoDatabase::class.java, "todo"
+ ).build()
+
+ // db의 결과를 관찰
+ private val _items = MutableStateFlow>(emptyList())
+ val items: StateFlow> = _items
+
+ // 초기화시 모든 데이터를 읽어 옴
+ init {
+ viewModelScope.launch {
+ db.todoDao().getAll().collect { todos ->
+ _items.value = todos
+ }
+ }
+ }
+
+ // 추가
+ fun addTodo(todo: Todo) { // Modify this line
+ viewModelScope.launch {
+ db.todoDao().insert(todo) // Modify this line
+ }
+ }
+
+ fun deleteTodo(id: Long) {
+ _items.value
+ .find { todo -> todo.id == id }
+ ?.let { todo ->
+ viewModelScope.launch {
+ db.todoDao().delete(todo)
+ }
+ }
+ }
+
+ private val _selectedDateTodos = MutableStateFlow>(emptyList())
+ val selectedDateTodos: StateFlow> = _selectedDateTodos
+
+ fun getTodosBySelectedDate(selectedDate: Long) {
+ viewModelScope.launch {
+ db.todoDao().getTodosByDate(selectedDate).collect { todos ->
+ _selectedDateTodos.value = todos
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/Apic/apic/MemberData.kt b/app/src/main/java/com/Apic/apic/MemberData.kt
new file mode 100644
index 0000000..53614c8
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/MemberData.kt
@@ -0,0 +1,12 @@
+package com.Apic.apic
+
+class MemberData (
+ val email : String,
+ val name : String,
+ //val password : String,
+){
+ @JvmName("callFromString")
+ fun getName(): String {
+ return name
+ }
+}
diff --git a/app/src/main/java/com/Apic/apic/MemberFragment.kt b/app/src/main/java/com/Apic/apic/MemberFragment.kt
index 21f000d..ca275af 100644
--- a/app/src/main/java/com/Apic/apic/MemberFragment.kt
+++ b/app/src/main/java/com/Apic/apic/MemberFragment.kt
@@ -1,14 +1,16 @@
package com.Apic.apic
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.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.Apic.apic.databinding.FragmentDateBinding
import com.Apic.apic.databinding.FragmentMemberBinding
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.firestore.FirebaseFirestore
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@@ -25,8 +27,14 @@ class MemberFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
+ private lateinit var binding: FragmentMemberBinding
+ private val db = FirebaseFirestore.getInstance()
+ private lateinit var auth: FirebaseAuth
+
private lateinit var groupMemberAdapter: GroupMemberAdapter
+ private val memberList = mutableListOf()
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
@@ -40,19 +48,46 @@ class MemberFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
- val binding = FragmentMemberBinding.inflate(inflater, container, false)
- var list = arrayListOf("Name_A","Name_B","Name_C","Name_D","Name_E","Name_F","Name_G")
+ binding = FragmentMemberBinding.inflate(inflater, container, false)
+
+ auth = FirebaseAuth.getInstance()
val recyclerView: RecyclerView = binding.groupMemberRecyclerView
recyclerView.layoutManager = GridLayoutManager(context, 4)
- groupMemberAdapter = GroupMemberAdapter()
- groupMemberAdapter.replaceList(list)
+ groupMemberAdapter = GroupMemberAdapter(memberList)
recyclerView.adapter = groupMemberAdapter
+// val groupName = arguments?.getString("g_name")
+ // 오류사항 - 시연때 그룹이름 픽스
+ val groupName = "appic"
+ getMemberData(groupName)
return binding.root
}
+ private fun getMemberData(g_name:String) {
+ db.collection("memberDB")
+ .document(auth.currentUser!!.email.toString())
+ .collection("groups")
+ .document(g_name)
+ .collection("participants")
+ .get()
+ .addOnSuccessListener { result ->
+ memberList.clear()
+ for (document in result) {
+ val member = GroupMemberData (
+ document["f_email"] as String,
+ )
+ memberList.add(member)
+ }
+ groupMemberAdapter.notifyDataSetChanged()
+ Log.d("db", "success")
+ }
+ .addOnFailureListener {
+ Log.d("db", "fail")
+ }
+ }
+
companion object {
/**
* Use this factory method to create a new instance of
diff --git a/app/src/main/java/com/Apic/apic/SecondFragment.kt b/app/src/main/java/com/Apic/apic/SecondFragment.kt
deleted file mode 100644
index 65282fa..0000000
--- a/app/src/main/java/com/Apic/apic/SecondFragment.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.Apic.apic
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-
-// TODO: Rename parameter arguments, choose names that match
-// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
-private const val ARG_PARAM1 = "param1"
-private const val ARG_PARAM2 = "param2"
-
-/**
- * A simple [Fragment] subclass.
- * Use the [SecondFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
-class SecondFragment : Fragment() {
- // TODO: Rename and change types of parameters
- private var param1: String? = null
- private var param2: String? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- arguments?.let {
- param1 = it.getString(ARG_PARAM1)
- param2 = it.getString(ARG_PARAM2)
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.fragment_second, container, false)
- }
-
- companion object {
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment FreindsFragment.
- */
- // TODO: Rename and change types and number of parameters
- @JvmStatic
- fun newInstance(param1: String, param2: String) =
- SecondFragment().apply {
- arguments = Bundle().apply {
- putString(ARG_PARAM1, param1)
- putString(ARG_PARAM2, param2)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/TodoDiffUtilCallback.kt b/app/src/main/java/com/Apic/apic/TodoDiffUtilCallback.kt
new file mode 100644
index 0000000..a613b0d
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/TodoDiffUtilCallback.kt
@@ -0,0 +1,14 @@
+package com.Apic.apic
+
+import androidx.recyclerview.widget.DiffUtil
+import com.Apic.apic.data.Todo
+class TodoDiffUtilCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Todo, newItem: Todo): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItem: Todo, newItem: Todo): Boolean {
+ // 내용이 변경되었을 때만 false를 반환하도록 수정
+ return oldItem == newItem
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/TodoListAdapter.kt b/app/src/main/java/com/Apic/apic/TodoListAdapter.kt
new file mode 100644
index 0000000..9d1d688
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/TodoListAdapter.kt
@@ -0,0 +1,45 @@
+package com.Apic.apic
+
+import android.text.format.DateFormat
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import com.Apic.apic.data.Todo
+import com.Apic.apic.databinding.ItemTodoBinding
+import androidx.recyclerview.widget.RecyclerView
+
+
+class TodoListAdapter(
+ private val onClick: (Todo) -> Unit
+) : ListAdapter(TodoDiffUtilCallback()) {
+
+ // ViewHolder 생성, 반환
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
+ val binding = ItemTodoBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return TodoViewHolder(binding, onClick)
+ }
+
+ // ViewHolder와 데이터 바인딩
+ override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ holder.setOnClickListener(getItem(position))
+ }
+
+ // ViewHolder
+ class TodoViewHolder(
+ private val binding: ItemTodoBinding,
+ private val onClick: (Todo) -> Unit
+ ) : RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(todo: Todo) {
+ binding.text1.text = todo.title
+ binding.text2.text = DateFormat.format("yyyy/MM/dd", todo.date)
+ }
+
+ fun setOnClickListener(todo: Todo) {
+ binding.root.setOnClickListener {
+ onClick(todo)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/Apic/apic/data/Todo.kt b/app/src/main/java/com/Apic/apic/data/Todo.kt
new file mode 100644
index 0000000..436a1e3
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/data/Todo.kt
@@ -0,0 +1,14 @@
+package com.Apic.apic.data
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.util.Calendar
+
+@Entity
+data class Todo(
+ val title:String,
+ val date: Long = Calendar.getInstance().timeInMillis
+){
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/data/TodoDao.kt b/app/src/main/java/com/Apic/apic/data/TodoDao.kt
new file mode 100644
index 0000000..e2697cd
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/data/TodoDao.kt
@@ -0,0 +1,24 @@
+package com.Apic.apic.data
+
+
+import androidx.room.*
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+
+@Dao
+interface TodoDao {
+ @Query("SELECT * FROM todo WHERE date")
+ fun getAll(): Flow>
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insert(entity: Todo)
+
+ @Delete
+ suspend fun delete(entity: Todo)
+
+ @Query("SELECT * FROM todo WHERE date = :selectedDate ORDER BY date DESC")
+ fun getByDate(selectedDate: Long): List
+
+ @Query("SELECT * FROM todo WHERE date = :selectedDate ORDER BY date DESC")
+ fun getTodosByDate(selectedDate: Long): Flow>
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/data/TodoDao_Impl.java b/app/src/main/java/com/Apic/apic/data/TodoDao_Impl.java
new file mode 100644
index 0000000..e64f41b
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/data/TodoDao_Impl.java
@@ -0,0 +1,236 @@
+package com.Apic.apic.data;
+
+import android.database.Cursor;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.room.CoroutinesRoom;
+import androidx.room.EntityDeletionOrUpdateAdapter;
+import androidx.room.EntityInsertionAdapter;
+import androidx.room.RoomDatabase;
+import androidx.room.RoomSQLiteQuery;
+import androidx.room.util.CursorUtil;
+import androidx.room.util.DBUtil;
+import androidx.sqlite.db.SupportSQLiteStatement;
+import java.lang.Class;
+import java.lang.Exception;
+import java.lang.Object;
+import java.lang.Override;
+import java.lang.String;
+import java.lang.SuppressWarnings;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import kotlin.Unit;
+import kotlin.coroutines.Continuation;
+import kotlinx.coroutines.flow.Flow;
+
+@SuppressWarnings({"unchecked", "deprecation"})
+public final class TodoDao_Impl implements TodoDao {
+ private final RoomDatabase __db;
+
+ private final EntityInsertionAdapter __insertionAdapterOfTodo;
+
+ private final EntityDeletionOrUpdateAdapter __deletionAdapterOfTodo;
+
+ public TodoDao_Impl(@NonNull final RoomDatabase __db) {
+ this.__db = __db;
+ this.__insertionAdapterOfTodo = new EntityInsertionAdapter(__db) {
+ @Override
+ @NonNull
+ protected String createQuery() {
+ return "INSERT OR REPLACE INTO `Todo` (`title`,`date`,`id`) VALUES (?,?,nullif(?, 0))";
+ }
+
+ @Override
+ protected void bind(@NonNull final SupportSQLiteStatement statement,
+ @Nullable final Todo entity) {
+ if (entity.getTitle() == null) {
+ statement.bindNull(1);
+ } else {
+ statement.bindString(1, entity.getTitle());
+ }
+ statement.bindLong(2, entity.getDate());
+ statement.bindLong(3, entity.getId());
+ }
+ };
+ this.__deletionAdapterOfTodo = new EntityDeletionOrUpdateAdapter(__db) {
+ @Override
+ @NonNull
+ protected String createQuery() {
+ return "DELETE FROM `Todo` WHERE `id` = ?";
+ }
+
+ @Override
+ protected void bind(@NonNull final SupportSQLiteStatement statement,
+ @Nullable final Todo entity) {
+ statement.bindLong(1, entity.getId());
+ }
+ };
+ }
+
+ @Override
+ public Object insert(final Todo entity, final Continuation super Unit> continuation) {
+ return CoroutinesRoom.execute(__db, true, new Callable() {
+ @Override
+ @NonNull
+ public Unit call() throws Exception {
+ __db.beginTransaction();
+ try {
+ __insertionAdapterOfTodo.insert(entity);
+ __db.setTransactionSuccessful();
+ return Unit.INSTANCE;
+ } finally {
+ __db.endTransaction();
+ }
+ }
+ }, continuation);
+ }
+
+ @Override
+ public Object delete(final Todo entity, final Continuation super Unit> continuation) {
+ return CoroutinesRoom.execute(__db, true, new Callable() {
+ @Override
+ @NonNull
+ public Unit call() throws Exception {
+ __db.beginTransaction();
+ try {
+ __deletionAdapterOfTodo.handle(entity);
+ __db.setTransactionSuccessful();
+ return Unit.INSTANCE;
+ } finally {
+ __db.endTransaction();
+ }
+ }
+ }, continuation);
+ }
+
+ @Override
+ public Flow> getAll() {
+ final String _sql = "SELECT * FROM todo WHERE date";
+ final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
+ return CoroutinesRoom.createFlow(__db, false, new String[] {"todo"}, new Callable>() {
+ @Override
+ @NonNull
+ public List call() throws Exception {
+ final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
+ try {
+ final int _cursorIndexOfTitle = CursorUtil.getColumnIndexOrThrow(_cursor, "title");
+ final int _cursorIndexOfDate = CursorUtil.getColumnIndexOrThrow(_cursor, "date");
+ final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
+ final List _result = new ArrayList(_cursor.getCount());
+ while (_cursor.moveToNext()) {
+ final Todo _item;
+ final String _tmpTitle;
+ if (_cursor.isNull(_cursorIndexOfTitle)) {
+ _tmpTitle = null;
+ } else {
+ _tmpTitle = _cursor.getString(_cursorIndexOfTitle);
+ }
+ final long _tmpDate;
+ _tmpDate = _cursor.getLong(_cursorIndexOfDate);
+ _item = new Todo(_tmpTitle,_tmpDate);
+ final long _tmpId;
+ _tmpId = _cursor.getLong(_cursorIndexOfId);
+ _item.setId(_tmpId);
+ _result.add(_item);
+ }
+ return _result;
+ } finally {
+ _cursor.close();
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ _statement.release();
+ }
+ });
+ }
+
+ @Override
+ public List getByDate(final long selectedDate) {
+ final String _sql = "SELECT * FROM todo WHERE date = ? ORDER BY date DESC";
+ final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
+ int _argIndex = 1;
+ _statement.bindLong(_argIndex, selectedDate);
+ __db.assertNotSuspendingTransaction();
+ final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
+ try {
+ final int _cursorIndexOfTitle = CursorUtil.getColumnIndexOrThrow(_cursor, "title");
+ final int _cursorIndexOfDate = CursorUtil.getColumnIndexOrThrow(_cursor, "date");
+ final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
+ final List _result = new ArrayList(_cursor.getCount());
+ while (_cursor.moveToNext()) {
+ final Todo _item;
+ final String _tmpTitle;
+ if (_cursor.isNull(_cursorIndexOfTitle)) {
+ _tmpTitle = null;
+ } else {
+ _tmpTitle = _cursor.getString(_cursorIndexOfTitle);
+ }
+ final long _tmpDate;
+ _tmpDate = _cursor.getLong(_cursorIndexOfDate);
+ _item = new Todo(_tmpTitle,_tmpDate);
+ final long _tmpId;
+ _tmpId = _cursor.getLong(_cursorIndexOfId);
+ _item.setId(_tmpId);
+ _result.add(_item);
+ }
+ return _result;
+ } finally {
+ _cursor.close();
+ _statement.release();
+ }
+ }
+
+ @Override
+ public Flow> getTodosByDate(final long selectedDate) {
+ final String _sql = "SELECT * FROM todo WHERE date = ? ORDER BY date DESC";
+ final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
+ int _argIndex = 1;
+ _statement.bindLong(_argIndex, selectedDate);
+ return CoroutinesRoom.createFlow(__db, false, new String[] {"todo"}, new Callable>() {
+ @Override
+ @NonNull
+ public List call() throws Exception {
+ final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
+ try {
+ final int _cursorIndexOfTitle = CursorUtil.getColumnIndexOrThrow(_cursor, "title");
+ final int _cursorIndexOfDate = CursorUtil.getColumnIndexOrThrow(_cursor, "date");
+ final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
+ final List _result = new ArrayList(_cursor.getCount());
+ while (_cursor.moveToNext()) {
+ final Todo _item;
+ final String _tmpTitle;
+ if (_cursor.isNull(_cursorIndexOfTitle)) {
+ _tmpTitle = null;
+ } else {
+ _tmpTitle = _cursor.getString(_cursorIndexOfTitle);
+ }
+ final long _tmpDate;
+ _tmpDate = _cursor.getLong(_cursorIndexOfDate);
+ _item = new Todo(_tmpTitle,_tmpDate);
+ final long _tmpId;
+ _tmpId = _cursor.getLong(_cursorIndexOfId);
+ _item.setId(_tmpId);
+ _result.add(_item);
+ }
+ return _result;
+ } finally {
+ _cursor.close();
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ _statement.release();
+ }
+ });
+ }
+
+ @NonNull
+ public static List> getRequiredConverters() {
+ return Collections.emptyList();
+ }
+}
diff --git a/app/src/main/java/com/Apic/apic/data/TodoDatabase.kt b/app/src/main/java/com/Apic/apic/data/TodoDatabase.kt
new file mode 100644
index 0000000..fb9869d
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/data/TodoDatabase.kt
@@ -0,0 +1,10 @@
+package com.Apic.apic.data
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+
+@Database(entities = [Todo::class], version = 1, exportSchema = false)
+abstract class TodoDatabase : RoomDatabase(){
+ abstract fun todoDao(): TodoDao
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/Apic/apic/data/TodoDatabase_Impl.java b/app/src/main/java/com/Apic/apic/data/TodoDatabase_Impl.java
new file mode 100644
index 0000000..2536682
--- /dev/null
+++ b/app/src/main/java/com/Apic/apic/data/TodoDatabase_Impl.java
@@ -0,0 +1,169 @@
+package com.Apic.apic.data;
+
+import androidx.annotation.NonNull;
+import androidx.room.DatabaseConfiguration;
+import androidx.room.InvalidationTracker;
+import androidx.room.RoomDatabase;
+import androidx.room.RoomOpenHelper;
+import androidx.room.migration.AutoMigrationSpec;
+import androidx.room.migration.Migration;
+import androidx.room.util.DBUtil;
+import androidx.room.util.TableInfo;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+import androidx.sqlite.db.SupportSQLiteOpenHelper;
+import java.lang.Class;
+import java.lang.Override;
+import java.lang.String;
+import java.lang.SuppressWarnings;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@SuppressWarnings({"unchecked", "deprecation"})
+public final class TodoDatabase_Impl extends TodoDatabase {
+ private volatile TodoDao _todoDao;
+
+ @Override
+ @NonNull
+ protected SupportSQLiteOpenHelper createOpenHelper(@NonNull final DatabaseConfiguration config) {
+ final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(config, new RoomOpenHelper.Delegate(1) {
+ @Override
+ public void createAllTables(@NonNull final SupportSQLiteDatabase db) {
+ db.execSQL("CREATE TABLE IF NOT EXISTS `Todo` (`title` TEXT NOT NULL, `date` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
+ db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b612f5e0e508cf78cb0e0ab87953963f')");
+ }
+
+ @Override
+ public void dropAllTables(@NonNull final SupportSQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS `Todo`");
+ final List extends RoomDatabase.Callback> _callbacks = mCallbacks;
+ if (_callbacks != null) {
+ for (RoomDatabase.Callback _callback : _callbacks) {
+ _callback.onDestructiveMigration(db);
+ }
+ }
+ }
+
+ @Override
+ public void onCreate(@NonNull final SupportSQLiteDatabase db) {
+ final List extends RoomDatabase.Callback> _callbacks = mCallbacks;
+ if (_callbacks != null) {
+ for (RoomDatabase.Callback _callback : _callbacks) {
+ _callback.onCreate(db);
+ }
+ }
+ }
+
+ @Override
+ public void onOpen(@NonNull final SupportSQLiteDatabase db) {
+ mDatabase = db;
+ internalInitInvalidationTracker(db);
+ final List extends RoomDatabase.Callback> _callbacks = mCallbacks;
+ if (_callbacks != null) {
+ for (RoomDatabase.Callback _callback : _callbacks) {
+ _callback.onOpen(db);
+ }
+ }
+ }
+
+ @Override
+ public void onPreMigrate(@NonNull final SupportSQLiteDatabase db) {
+ DBUtil.dropFtsSyncTriggers(db);
+ }
+
+ @Override
+ public void onPostMigrate(@NonNull final SupportSQLiteDatabase db) {
+ }
+
+ @Override
+ @NonNull
+ public RoomOpenHelper.ValidationResult onValidateSchema(
+ @NonNull final SupportSQLiteDatabase db) {
+ final HashMap _columnsTodo = new HashMap(3);
+ _columnsTodo.put("title", new TableInfo.Column("title", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
+ _columnsTodo.put("date", new TableInfo.Column("date", "INTEGER", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
+ _columnsTodo.put("id", new TableInfo.Column("id", "INTEGER", true, 1, null, TableInfo.CREATED_FROM_ENTITY));
+ final HashSet _foreignKeysTodo = new HashSet(0);
+ final HashSet _indicesTodo = new HashSet(0);
+ final TableInfo _infoTodo = new TableInfo("Todo", _columnsTodo, _foreignKeysTodo, _indicesTodo);
+ final TableInfo _existingTodo = TableInfo.read(db, "Todo");
+ if (!_infoTodo.equals(_existingTodo)) {
+ return new RoomOpenHelper.ValidationResult(false, "Todo(com.Apic.apic.data.Todo).\n"
+ + " Expected:\n" + _infoTodo + "\n"
+ + " Found:\n" + _existingTodo);
+ }
+ return new RoomOpenHelper.ValidationResult(true, null);
+ }
+ }, "b612f5e0e508cf78cb0e0ab87953963f", "6583cdf08b8a1eba9b85d22d5b209782");
+ final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(config.context).name(config.name).callback(_openCallback).build();
+ final SupportSQLiteOpenHelper _helper = config.sqliteOpenHelperFactory.create(_sqliteConfig);
+ return _helper;
+ }
+
+ @Override
+ @NonNull
+ protected InvalidationTracker createInvalidationTracker() {
+ final HashMap _shadowTablesMap = new HashMap(0);
+ final HashMap> _viewTables = new HashMap>(0);
+ return new InvalidationTracker(this, _shadowTablesMap, _viewTables, "Todo");
+ }
+
+ @Override
+ public void clearAllTables() {
+ super.assertNotMainThread();
+ final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
+ try {
+ super.beginTransaction();
+ _db.execSQL("DELETE FROM `Todo`");
+ super.setTransactionSuccessful();
+ } finally {
+ super.endTransaction();
+ _db.query("PRAGMA wal_checkpoint(FULL)").close();
+ if (!_db.inTransaction()) {
+ _db.execSQL("VACUUM");
+ }
+ }
+ }
+
+ @Override
+ @NonNull
+ protected Map, List>> getRequiredTypeConverters() {
+ final HashMap, List>> _typeConvertersMap = new HashMap, List>>();
+ _typeConvertersMap.put(TodoDao.class, TodoDao_Impl.getRequiredConverters());
+ return _typeConvertersMap;
+ }
+
+ @Override
+ @NonNull
+ public Set> getRequiredAutoMigrationSpecs() {
+ final HashSet> _autoMigrationSpecsSet = new HashSet>();
+ return _autoMigrationSpecsSet;
+ }
+
+ @Override
+ @NonNull
+ public List getAutoMigrations(
+ @NonNull final Map, AutoMigrationSpec> autoMigrationSpecs) {
+ final List _autoMigrations = new ArrayList();
+ return _autoMigrations;
+ }
+
+ @Override
+ public TodoDao todoDao() {
+ if (_todoDao != null) {
+ return _todoDao;
+ } else {
+ synchronized(this) {
+ if(_todoDao == null) {
+ _todoDao = new TodoDao_Impl(this);
+ }
+ return _todoDao;
+ }
+ }
+ }
+}
+
diff --git a/app/src/main/res/drawable/black_circle_button.xml b/app/src/main/res/drawable/black_circle_button.xml
new file mode 100644
index 0000000..0fb0e59
--- /dev/null
+++ b/app/src/main/res/drawable/black_circle_button.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_round.xml b/app/src/main/res/drawable/button_round.xml
new file mode 100644
index 0000000..acf1dba
--- /dev/null
+++ b/app/src/main/res/drawable/button_round.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/fourcut_blue_img.png b/app/src/main/res/drawable/fourcut_blue_img.png
new file mode 100644
index 0000000..d128c0c
Binary files /dev/null and b/app/src/main/res/drawable/fourcut_blue_img.png differ
diff --git a/app/src/main/res/drawable/fourcut_green_img.png b/app/src/main/res/drawable/fourcut_green_img.png
new file mode 100644
index 0000000..e521263
Binary files /dev/null and b/app/src/main/res/drawable/fourcut_green_img.png differ
diff --git a/app/src/main/res/drawable/fourcut_orange_img.png b/app/src/main/res/drawable/fourcut_orange_img.png
new file mode 100644
index 0000000..d6a2e0e
Binary files /dev/null and b/app/src/main/res/drawable/fourcut_orange_img.png differ
diff --git a/app/src/main/res/drawable/gray_circle_button.xml b/app/src/main/res/drawable/gray_circle_button.xml
new file mode 100644
index 0000000..9489672
--- /dev/null
+++ b/app/src/main/res/drawable/gray_circle_button.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_cancel_circle_close_delete_discard_icon.png b/app/src/main/res/drawable/ic_cancel_circle_close_delete_discard_icon.png
new file mode 100644
index 0000000..fcbf8f5
Binary files /dev/null and b/app/src/main/res/drawable/ic_cancel_circle_close_delete_discard_icon.png differ
diff --git a/app/src/main/res/drawable/ic_check_circle_icon.png b/app/src/main/res/drawable/ic_check_circle_icon.png
new file mode 100644
index 0000000..7060b8e
Binary files /dev/null and b/app/src/main/res/drawable/ic_check_circle_icon.png differ
diff --git a/app/src/main/res/drawable/ic_close_icon.png b/app/src/main/res/drawable/ic_close_icon.png
new file mode 100644
index 0000000..60dcc07
Binary files /dev/null and b/app/src/main/res/drawable/ic_close_icon.png differ
diff --git a/app/src/main/res/drawable/ic_dot_list_menu_icon.png b/app/src/main/res/drawable/ic_dot_list_menu_icon.png
new file mode 100644
index 0000000..75d8f8c
Binary files /dev/null and b/app/src/main/res/drawable/ic_dot_list_menu_icon.png differ
diff --git a/app/src/main/res/drawable/ic_friend.png b/app/src/main/res/drawable/ic_friend.png
new file mode 100644
index 0000000..2a67a0a
Binary files /dev/null and b/app/src/main/res/drawable/ic_friend.png differ
diff --git a/app/src/main/res/drawable/ic_group.png b/app/src/main/res/drawable/ic_group.png
new file mode 100644
index 0000000..c6f89c3
Binary files /dev/null and b/app/src/main/res/drawable/ic_group.png differ
diff --git a/app/src/main/res/drawable/ic_search_window.xml b/app/src/main/res/drawable/ic_search_window.xml
new file mode 100644
index 0000000..6d444cd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_search_window.xml
@@ -0,0 +1,10 @@
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_send_icon.png b/app/src/main/res/drawable/ic_send_icon.png
new file mode 100644
index 0000000..d4d5d9f
Binary files /dev/null and b/app/src/main/res/drawable/ic_send_icon.png differ
diff --git a/app/src/main/res/drawable/iv_fourcut_frame.png b/app/src/main/res/drawable/iv_fourcut_frame.png
new file mode 100644
index 0000000..b094fa4
Binary files /dev/null and b/app/src/main/res/drawable/iv_fourcut_frame.png differ
diff --git a/app/src/main/res/drawable/iv_fourcut_frame_white.png b/app/src/main/res/drawable/iv_fourcut_frame_white.png
new file mode 100644
index 0000000..8a0f733
Binary files /dev/null and b/app/src/main/res/drawable/iv_fourcut_frame_white.png differ
diff --git a/app/src/main/res/drawable/radius20.xml b/app/src/main/res/drawable/radius20.xml
index 6b5c39d..24b8595 100644
--- a/app/src/main/res/drawable/radius20.xml
+++ b/app/src/main/res/drawable/radius20.xml
@@ -4,4 +4,5 @@
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shrimp_kang.jpg b/app/src/main/res/drawable/shrimp_kang.jpg
new file mode 100644
index 0000000..7a7acbf
Binary files /dev/null and b/app/src/main/res/drawable/shrimp_kang.jpg differ
diff --git a/app/src/main/res/drawable/white_circle_button.xml b/app/src/main/res/drawable/white_circle_button.xml
new file mode 100644
index 0000000..fbd1790
--- /dev/null
+++ b/app/src/main/res/drawable/white_circle_button.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/acticity_group.xml b/app/src/main/res/layout/activity_group.xml
similarity index 100%
rename from app/src/main/res/layout/acticity_group.xml
rename to app/src/main/res/layout/activity_group.xml
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 5a220d5..b5fbbaa 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -67,5 +67,4 @@
android:text="login / sign up" />
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_add_friend.xml b/app/src/main/res/layout/fragment_add_friend.xml
new file mode 100644
index 0000000..fe6466a
--- /dev/null
+++ b/app/src/main/res/layout/fragment_add_friend.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_add_group.xml b/app/src/main/res/layout/fragment_add_group.xml
index d4fe810..dd95538 100644
--- a/app/src/main/res/layout/fragment_add_group.xml
+++ b/app/src/main/res/layout/fragment_add_group.xml
@@ -44,14 +44,14 @@
android:layout_marginLeft="8dp"/>
-
@@ -85,7 +85,7 @@
android:layout_marginBottom="10dp">
+ android:text=""
+ android:inputType="number"/>
+
-
+ android:text="친구목록에서 친구를 선택하여 참여자를 추가해주세요."/>
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_album.xml b/app/src/main/res/layout/fragment_album.xml
new file mode 100644
index 0000000..305b63a
--- /dev/null
+++ b/app/src/main/res/layout/fragment_album.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_calendar.xml b/app/src/main/res/layout/fragment_calendar.xml
index 61796f9..a12e0bf 100644
--- a/app/src/main/res/layout/fragment_calendar.xml
+++ b/app/src/main/res/layout/fragment_calendar.xml
@@ -1,30 +1,61 @@
-
+ android:layout_height="match_parent">
+ app:layout_constraintEnd_toEndOf="parent"
+ android:layout_marginTop="16dp"
+ tools:ignore="MissingConstraints" />
-
+
+
+
+
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ android:layout_marginTop="16dp">
-
\ No newline at end of file
+
+
+
diff --git a/app/src/main/res/layout/fragment_first.xml b/app/src/main/res/layout/fragment_first.xml
deleted file mode 100644
index f260270..0000000
--- a/app/src/main/res/layout/fragment_first.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_fourcut.xml b/app/src/main/res/layout/fragment_fourcut.xml
new file mode 100644
index 0000000..ac54636
--- /dev/null
+++ b/app/src/main/res/layout/fragment_fourcut.xml
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_friend.xml b/app/src/main/res/layout/fragment_friend.xml
index 21d5567..99e2d9e 100644
--- a/app/src/main/res/layout/fragment_friend.xml
+++ b/app/src/main/res/layout/fragment_friend.xml
@@ -9,40 +9,51 @@
+ android:background="@drawable/ic_search_window"
+ android:iconifiedByDefault="false"
+ android:layout_marginTop="5dp"
+ android:layout_marginRight="5dp"
+ android:hint="친구명 검색"
+ app:iconifiedByDefault="false"
+ app:queryHint="친구명 검색" />
-
-
diff --git a/app/src/main/res/layout/fragment_group_list.xml b/app/src/main/res/layout/fragment_group_list.xml
index 43a35bc..3066fbf 100644
--- a/app/src/main/res/layout/fragment_group_list.xml
+++ b/app/src/main/res/layout/fragment_group_list.xml
@@ -26,16 +26,17 @@
android:orientation="horizontal">
-
diff --git a/app/src/main/res/layout/fragment_second.xml b/app/src/main/res/layout/fragment_second.xml
deleted file mode 100644
index 9017c01..0000000
--- a/app/src/main/res/layout/fragment_second.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/friend_add_recyclerview.xml b/app/src/main/res/layout/friend_add_recyclerview.xml
new file mode 100644
index 0000000..d371819
--- /dev/null
+++ b/app/src/main/res/layout/friend_add_recyclerview.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/friend_recyclerview.xml b/app/src/main/res/layout/friend_recyclerview.xml
index a8d795c..c2e1b60 100644
--- a/app/src/main/res/layout/friend_recyclerview.xml
+++ b/app/src/main/res/layout/friend_recyclerview.xml
@@ -9,38 +9,41 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
- android:padding="20dp"
- android:background="#c3cad1">
+ android:padding="10dp"
+ android:background="@color/mainColor1"
+ android:elevation="10dp">
+ android:layout_width="90dp"
+ android:layout_height="90dp"
+ android:src="@drawable/ic_friend"
+ android:layout_marginLeft="10dp"
+ />
+
@@ -52,16 +55,14 @@
android:layout_height="0dp"
android:layout_weight="1"/>
-
+
@@ -69,7 +70,6 @@
+ android:layout_marginBottom="10dp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_picture.xml b/app/src/main/res/layout/item_picture.xml
new file mode 100644
index 0000000..4f38542
--- /dev/null
+++ b/app/src/main/res/layout/item_picture.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_todo.xml b/app/src/main/res/layout/item_todo.xml
new file mode 100644
index 0000000..86daba2
--- /dev/null
+++ b/app/src/main/res/layout/item_todo.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/rv_group_list.xml b/app/src/main/res/layout/rv_group_list.xml
index 78bb6fd..8f5fe15 100644
--- a/app/src/main/res/layout/rv_group_list.xml
+++ b/app/src/main/res/layout/rv_group_list.xml
@@ -26,7 +26,7 @@
app:srcCompat="@drawable/ic_gallery" />
diff --git a/app/src/main/res/layout/rv_group_member.xml b/app/src/main/res/layout/rv_group_member.xml
index 5e38988..eafa8ac 100644
--- a/app/src/main/res/layout/rv_group_member.xml
+++ b/app/src/main/res/layout/rv_group_member.xml
@@ -5,15 +5,14 @@
android:layout_height="wrap_content"
android:id="@+id/layoutListItem"
android:orientation="vertical"
- android:layout_marginHorizontal="20dp"
+ android:layout_marginHorizontal="10dp"
android:layout_gravity="center">
+ android:layout_width="70dp"
+ android:layout_height="70dp"
+ android:src="@drawable/ic_friend"/>
@@ -15,7 +15,7 @@
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_margin="10dp"
- android:src="@drawable/ic_person_circle"
+ android:src="@drawable/ic_friend"
android:background="@drawable/ic_circle_button"/>
diff --git a/app/src/main/res/menu/toolbar_menu.xml b/app/src/main/res/menu/toolbar_menu.xml
index 06e175a..b3e1e7b 100644
--- a/app/src/main/res/menu/toolbar_menu.xml
+++ b/app/src/main/res/menu/toolbar_menu.xml
@@ -5,8 +5,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_app.png b/app/src/main/res/mipmap-hdpi/ic_app.png
new file mode 100644
index 0000000..5340400
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_app.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_app.png b/app/src/main/res/mipmap-mdpi/ic_app.png
new file mode 100644
index 0000000..62453ef
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_app.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_app.png b/app/src/main/res/mipmap-xhdpi/ic_app.png
new file mode 100644
index 0000000..71695c9
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_app.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_app.png b/app/src/main/res/mipmap-xxhdpi/ic_app.png
new file mode 100644
index 0000000..f044e74
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_app.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_app.png b/app/src/main/res/mipmap-xxxhdpi/ic_app.png
new file mode 100644
index 0000000..7af27c4
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_app.png differ
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..e189f78
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,4 @@
+
+
+ 150dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/ic_app_background.xml b/app/src/main/res/values/ic_app_background.xml
new file mode 100644
index 0000000..4ebe113
--- /dev/null
+++ b/app/src/main/res/values/ic_app_background.xml
@@ -0,0 +1,4 @@
+
+
+ #272C31
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f210ae2..98c8715 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,4 @@
-
Apic
Opened Drawer
Closed Drawer
@@ -7,5 +6,4 @@
Hello blank fragment
GroupActivity
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml
new file mode 100644
index 0000000..e35e919
--- /dev/null
+++ b/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/example/appapicprj/ExampleUnitTest.kt b/app/src/test/java/com/example/appapicprj/ExampleUnitTest.kt
new file mode 100644
index 0000000..946de2a
--- /dev/null
+++ b/app/src/test/java/com/example/appapicprj/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.appapicprj
+
+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/build.gradle b/build.gradle
index 97ca74f..8ab3b21 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,4 +9,5 @@ plugins {
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
id("com.google.gms.google-services") version "4.4.0" apply false
-}
\ No newline at end of file
+}
+
diff --git a/settings.gradle b/settings.gradle
index 91d6090..849638c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -14,3 +14,4 @@ dependencyResolutionManagement {
}
rootProject.name = "Apic"
include ':app'
+include ':opencv'
diff --git a/todo.db b/todo.db
new file mode 100644
index 0000000..1db515f
--- /dev/null
+++ b/todo.db
@@ -0,0 +1 @@
+S
\ No newline at end of file