diff --git a/.gitignore b/.gitignore
index aa724b7..91ba8e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,156 @@
-*.iml
+# Created by https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin
+# Edit at https://www.toptal.com/developers/gitignore?templates=androidstudio,kotlin
+
+### Kotlin ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
+
+### AndroidStudio ###
+# Covers files to be ignored for android development using Android Studio.
+
+# Built application files
+*.apk
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
.gradle
-/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
-.DS_Store
-/build
-/captures
-.externalNativeBuild
-.cxx
+.gradle/
+build/
+
+# Signing files
+.signing/
+
+# Local configuration file (sdk path, etc)
local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+
+# Android Studio
+/*/build/
+/*/local.properties
+/*/out
+/*/*/build
+/*/*/production
+captures/
+.navigation/
+*.ipr
+*~
+*.swp
+
+# Keystore files
+*.jks
+*.keystore
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Android Patch
+gen-external-apklibs
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+
+# NDK
+obj/
+
+# IntelliJ IDEA
+*.iml
+*.iws
+/out/
+
+# User-specific configurations
+.idea/caches/
+.idea/libraries/
+.idea/shelf/
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/.name
+.idea/compiler.xml
+.idea/copyright/profiles_settings.xml
+.idea/encodings.xml
+.idea/misc.xml
+.idea/modules.xml
+.idea/scopes/scope_settings.xml
+.idea/dictionaries
+.idea/vcs.xml
+.idea/jsLibraryMappings.xml
+.idea/datasources.xml
+.idea/dataSources.ids
+.idea/sqlDataSources.xml
+.idea/dynamic.xml
+.idea/uiDesigner.xml
+.idea/assetWizardSettings.xml
+.idea/gradle.xml
+.idea/jarRepositories.xml
+.idea/navEditor.xml
+
+# Legacy Eclipse project files
+.classpath
+.project
+.cproject
+.settings/
+
+# Mobile Tools for Java (J2ME)
+
+# Package Files #
+
+# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
+
+## Plugin-specific files:
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Mongo Explorer plugin
+.idea/mongoSettings.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+### AndroidStudio Patch ###
+
+!/gradle/wrapper/gradle-wrapper.jar
+
+# End of https://www.toptal.com/developers/gitignore/api/androidstudio,kotlin
\ No newline at end of file
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 7d32cbb..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Everymoment
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index b589d56..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 0897082..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 971db29..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index bd60fe7..d80a087 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,27 @@
# Team21_Android
21조 안드로이드
-## 코드 리뷰 받고 싶은 부분 (개발 질문): 5주차
+## 코드 리뷰 받고 싶은 부분 (개발 질문): 6주차
+
+### todlf
+[이슈 #29](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/29)
+[이슈 #30](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/30)
+- FCM으로 알림을 받을 때, 백그라운드에서도 remoteView를 이용한 커스텀 알림이 가능한지 궁금합니다.
+- 앱이 종료되었는데 알림이 올 경우, 알림에서 이모지를 눌러서 백엔드에 데이터를 보낼 수 있는지 궁금합니다.(이모지 상호작용 알림은 포그라운드 알림에서 처리하는게 나을까요?)
+- 백엔드에서 알림 API를 받아와서 FCM으로 핸드폰으로 알림을 보내주는 걸 구현하려고 하는데,
+- 이 과정을 어떤 식으로 처리하는지 궁금합니다.(어떻게 해야할지 감이 안 잡힙니다 ㅠㅠ)
+- #29,30 이슈 해결방법이 궁금합니다.
+
+---
+
+### arieum
+- 이번주 PR에는 서버주소랑 jwtToken이 하드코딩되어있습니다! 다음 PR에는 추상화해서 올리겠습니다
+- friend_item.xml 에서 모든 뷰들을 layout_gravity를 center로 설정해도 이미지와 텍스트뷰가 가운데정렬이 되지 않습니다. vertical_center로 설정해도 안되는데 어떻게 처리해야하는지 궁금합니다
+- 5주차 코드리뷰 이제 확인해서 그부분도 다음 PR때 반영해서 올리겠습니다
+
+---
### settle54
-[이슈 #20](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/20)
-[이슈 #25](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/25)
-[이슈 #28](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/28)
-- 이슈 20, 이슈25, 이슈28에 대한 해결방법을 알고 싶습니다.
-- 불필요하거나 비효율적인 코드가 있으면 개선받고 싶습니다! (카테고리를 추가하는 코드가 많이 스파게티가 된 것 같습니다...)
+[이슈 #36](https://github.com/kakao-tech-campus-2nd-step3/Team21_Android/issues/36)
+- 이슈 36에 대한 해결방법을 알고 싶습니다.
+- 불필요하거나 비효율적인 코드가 있으면 개선받고 싶습니다!
diff --git a/app/.gitignore b/app/.gitignore
index 42afabf..65d12b9 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1,2 @@
-/build
\ No newline at end of file
+/build
+google-services.json
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 713f063..94e0d5c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -5,6 +5,7 @@ import java.util.Properties
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
+ id("com.google.gms.google-services")
}
fun getApiKey(key: String): String = gradleLocalProperties(rootDir, providers).getProperty(key)
@@ -65,11 +66,16 @@ dependencies {
implementation(libs.okhttp)
implementation(libs.play.services.location)
implementation(libs.androidx.work.runtime.ktx)
+ implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6")
implementation("com.github.prolificinteractive:material-calendarview:2.0.1")
implementation ("com.jakewharton.threetenabp:threetenabp:1.2.1")
implementation ("com.google.android.material:material:1.2.0")
implementation ("com.kakao.sdk:v2-all:2.20.6")
implementation ("com.kakao.sdk:v2-user:2.20.6")
+ implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
+ implementation("com.google.firebase:firebase-analytics-ktx")
+ implementation("com.google.firebase:firebase-config-ktx:22.0.0")
+ implementation("com.google.firebase:firebase-messaging-ktx:24.0.0")
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index eab025c..2bf60b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,10 +21,32 @@
android:supportsRtl="true"
android:theme="@style/Theme.Everymoment"
tools:targetApi="31">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:exported="true"
+ android:screenOrientation="portrait">
@@ -37,11 +59,13 @@
+ android:name=".presentation.view.main.KakaoLoginActivity"
+ android:exported="false"
+ android:screenOrientation="portrait" />
+ android:name=".presentation.view.main.MainActivity"
+ android:exported="true"
+ android:screenOrientation="portrait">
diff --git a/app/src/main/java/com/example/everymoment/GlobalApplication.kt b/app/src/main/java/com/example/everymoment/GlobalApplication.kt
index 2b0b832..0198ab4 100644
--- a/app/src/main/java/com/example/everymoment/GlobalApplication.kt
+++ b/app/src/main/java/com/example/everymoment/GlobalApplication.kt
@@ -1,11 +1,16 @@
package com.example.everymoment
import android.app.Application
+import com.example.everymoment.data.model.PreferenceUtil
import com.kakao.sdk.common.KakaoSdk
class GlobalApplication : Application() {
+ companion object {
+ lateinit var prefs: PreferenceUtil
+ }
override fun onCreate() {
super.onCreate()
KakaoSdk.init(this, "${BuildConfig.KAKAO_NATIVE_KEY}")
+ prefs = PreferenceUtil(applicationContext)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/LocationService.kt b/app/src/main/java/com/example/everymoment/LocationService.kt
index a76841a..a5eff5b 100644
--- a/app/src/main/java/com/example/everymoment/LocationService.kt
+++ b/app/src/main/java/com/example/everymoment/LocationService.kt
@@ -17,7 +17,9 @@ import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import com.example.everymoment.data.model.NetworkUtil
+import com.example.everymoment.data.repository.DiaryEntry
import com.example.everymoment.data.repository.GooglePlacesResponse
+import com.example.everymoment.data.repository.LocationPoint
import com.google.android.gms.location.*
class LocationService : Service() {
@@ -55,6 +57,7 @@ class LocationService : Service() {
locationRequest = LocationRequest.Builder(Priority.PRIORITY_BALANCED_POWER_ACCURACY, LOCATION_UPDATE_INTERVAL)
.setMinUpdateIntervalMillis(LOCATION_UPDATE_INTERVAL)
.setMaxUpdateDelayMillis(LOCATION_UPDATE_INTERVAL)
+ .setWaitForAccurateLocation(false)
.build()
locationCallback = object : LocationCallback() {
@@ -84,20 +87,38 @@ class LocationService : Service() {
val latitude = location.latitude
val longitude = location.longitude
- getPlaceNamesFromCoordinates(latitude, longitude) { currentPlaceNames ->
+ getPlaceNamesFromCoordinates(latitude, longitude) { currentPlaceNames, currentAddresses ->
if (currentPlaceNames.isNotEmpty()) {
Log.d("myplace", "$currentPlaceNames")
val currentPlace = currentPlaceNames.firstOrNull()
+ val currentAddress = currentAddresses.firstOrNull()
- // 처음 위치 측정이거나 현재 위치가 이전과 다를 때
if (initialPlaceName == null || (currentPlace != null && !currentPlaceNames.contains(initialPlaceName!!))) {
initialPlaceName = currentPlace
- Log.d("arieum", "새 장소 측정: $initialPlaceName, 아직 전달 안함")
+ Log.d("arieum", "새 장소 측정: $initialPlaceName, $currentAddress 아직 전달 안함")
} else {
- // 장소가 같을 때
if (isFirstLocationUpdateAfterChange) {
- Log.d("arieum", "백엔드로 전달: $initialPlaceName")
- isFirstLocationUpdateAfterChange = false // 첫 전달 이후에는 false로 설정하여 다시 전달 안함
+ Log.d("arieum", "백엔드로 전달: $initialPlaceName, $currentAddress")
+
+ val locationData = DiaryEntry(
+ locationPoint = LocationPoint(latitude, longitude),
+ locationName = currentPlace ?: "알 수 없는 장소",
+ address = currentAddress ?: "알 수 없는 위치"
+ )
+
+ NetworkUtil.sendData(
+ "http://13.125.156.74:8080/api/diaries/auto",
+ "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwiaWF0IjoxNzI4NTM4MDgzLCJleHAiOjE3Mjg3MTA4ODN9.ohkjWMb5haJ-aNzXdivYTskLeKPHd-EIw9FYfbQerBo",
+ locationData
+ ) { success, code, message, infoObject ->
+ if (success) {
+ Log.d("arieum", "성공! 코드: $code, 메시지: $message, 정보: $infoObject")
+ } else {
+ Log.d("arieum", "실패!")
+ }
+ }
+
+ isFirstLocationUpdateAfterChange = false
} else {
Log.d("arieum", "세 번 이상 장소: $initialPlaceName, 더이상 전달 안함")
}
@@ -140,7 +161,7 @@ class LocationService : Service() {
private fun getPlaceNamesFromCoordinates(
latitude: Double,
longitude: Double,
- callback: (List) -> Unit
+ callback: (List, List) -> Unit
) {
val apiKey = BuildConfig.API_KEY
val url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json"
@@ -160,18 +181,19 @@ class LocationService : Service() {
if (success && response != null) {
try {
val placeNames = response.results.map { it.name }
- callback(placeNames)
+ val addresses = response.results.map { it.vicinity }
+ callback(placeNames, addresses)
} catch (e: Exception) {
- callback(emptyList())
+ callback(emptyList(), emptyList())
}
} else {
- callback(emptyList())
+ callback(emptyList(), emptyList())
}
}
}
companion object {
private const val NOTIFICATION_ID = 1
- private const val LOCATION_UPDATE_INTERVAL = 5 * 60 * 1000L // 5분
+ private const val LOCATION_UPDATE_INTERVAL = 3 * 60 * 1000L
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/NotificationActionReceiver.kt b/app/src/main/java/com/example/everymoment/NotificationActionReceiver.kt
new file mode 100644
index 0000000..3c73159
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/NotificationActionReceiver.kt
@@ -0,0 +1,36 @@
+package com.example.everymoment
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.widget.Toast
+import com.example.everymoment.data.model.Emotions
+
+class NotificationActionReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val emotion = when (intent.action) {
+ "${Emotions.HAPPY.name}_ACTION" -> Emotions.HAPPY
+ "${Emotions.SAD.name}_ACTION" -> Emotions.SAD
+ "${Emotions.INSENSITIVE.name}_ACTION" -> Emotions.INSENSITIVE
+ "${Emotions.ANGRY.name}_ACTION" -> Emotions.ANGRY
+ "${Emotions.CONFOUNDED.name}_ACTION" -> Emotions.CONFOUNDED
+ else -> null
+ }
+
+ emotion?.let { handleEmotion(context, it) }
+ }
+
+ private fun handleEmotion(context: Context, emotion: Emotions) {
+ val emoji = emotion.getEmotionUnicode()
+ val label = when (emotion) {
+ Emotions.HAPPY -> "행복"
+ Emotions.SAD -> "슬픔"
+ Emotions.INSENSITIVE -> "무표정"
+ Emotions.ANGRY -> "화남"
+ Emotions.CONFOUNDED -> "싫음"
+ }
+
+ // 선택된 감정 처리 -> 백엔드 전송 필요
+ Toast.makeText(context, "선택된 감정: $emoji $label", Toast.LENGTH_SHORT).show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/model/FriendRequest.kt b/app/src/main/java/com/example/everymoment/data/model/FriendRequestList.kt
similarity index 76%
rename from app/src/main/java/com/example/everymoment/data/model/FriendRequest.kt
rename to app/src/main/java/com/example/everymoment/data/model/FriendRequestList.kt
index eb42b54..9e6e314 100644
--- a/app/src/main/java/com/example/everymoment/data/model/FriendRequest.kt
+++ b/app/src/main/java/com/example/everymoment/data/model/FriendRequestList.kt
@@ -1,6 +1,6 @@
package com.example.everymoment.data.model
-data class FriendRequest(
+data class FriendRequestList(
val name: String,
val profileImage: String
)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/model/NetworkUtil.kt b/app/src/main/java/com/example/everymoment/data/model/NetworkUtil.kt
index b66bbb1..c723197 100644
--- a/app/src/main/java/com/example/everymoment/data/model/NetworkUtil.kt
+++ b/app/src/main/java/com/example/everymoment/data/model/NetworkUtil.kt
@@ -105,17 +105,14 @@ object NetworkUtil {
fun patchRequest(
url: String,
jwtToken: String,
- queryParams: Int? = null,
data: T? = null,
callback: (success: Boolean, response: String?) -> Unit
) {
- val fullUrl = if (queryParams != null) "$url?$queryParams" else url
-
val jsonBody = gson.toJson(data)
val requestBody = jsonBody.toRequestBody("application/json; charset=utf-8".toMediaType())
val request = Request.Builder()
- .url(fullUrl)
+ .url(url)
.patch(requestBody)
.addHeader("Authorization", "Bearer $jwtToken")
.build()
@@ -136,13 +133,11 @@ object NetworkUtil {
fun deleteRequest(
url: String,
jwtToken: String,
- queryParams: Int,
+ queryParams: Int? = null,
callback: (success: Boolean, response: String?) -> Unit
) {
- val fullUrl = "$url/$queryParams"
-
val request = Request.Builder()
- .url(fullUrl)
+ .url(url)
.delete()
.addHeader("Authorization", "Bearer $jwtToken")
.build()
diff --git a/app/src/main/java/com/example/everymoment/data/model/PreferenceUtil.kt b/app/src/main/java/com/example/everymoment/data/model/PreferenceUtil.kt
new file mode 100644
index 0000000..58a3e09
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/data/model/PreferenceUtil.kt
@@ -0,0 +1,17 @@
+package com.example.everymoment.data.model
+
+import android.content.Context
+import android.content.SharedPreferences
+
+class PreferenceUtil(context: Context) {
+ private val prefs: SharedPreferences =
+ context.getSharedPreferences("prefs_name", Context.MODE_PRIVATE)
+
+ fun getString(key: String, defValue: String): String {
+ return prefs.getString(key, defValue).toString()
+ }
+
+ fun setString(key: String, str: String) {
+ prefs.edit().putString(key, str).apply()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/model/Timeline.kt b/app/src/main/java/com/example/everymoment/data/model/Timeline.kt
deleted file mode 100644
index 4dcf87d..0000000
--- a/app/src/main/java/com/example/everymoment/data/model/Timeline.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.example.everymoment.data.model
-
-data class Timeline(val time: String,
- val buildingName: String,
- val address: String,
- val emoji: String?,
- val isDetailedDiary: Boolean)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/repository/DiaryRepository.kt b/app/src/main/java/com/example/everymoment/data/repository/DiaryRepository.kt
new file mode 100644
index 0000000..aad56fa
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/data/repository/DiaryRepository.kt
@@ -0,0 +1,73 @@
+package com.example.everymoment.data.repository
+
+import android.util.Log
+import com.example.everymoment.data.model.NetworkUtil
+
+class DiaryRepository {
+ private val jwtToken = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwiaWF0IjoxNzI4NTM4MDgzLCJleHAiOjE3Mjg3MTA4ODN9.ohkjWMb5haJ-aNzXdivYTskLeKPHd-EIw9FYfbQerBo"
+
+ fun getDiaries(
+ date: String,
+ callback: (Boolean, DiaryResponse?) -> Unit
+ ) {
+ val url = "http://13.125.156.74:8080/api/diaries/my"
+ val params = mapOf("date" to date)
+
+ NetworkUtil.getData(
+ url,
+ jwtToken,
+ params,
+ DiaryResponse::class.java
+ ) { success, response ->
+ callback(success, response)
+ }
+ }
+
+ fun updateBookmarkStatus(
+ diaryId: Int,
+ callback: (Boolean, String?) -> Unit
+ ) {
+ val url = "http://13.125.156.74:8080/api/diaries/$diaryId/bookmark"
+
+ NetworkUtil.patchRequest(
+ url,
+ jwtToken,
+ null
+ ) { success, message ->
+ Log.d("arieum", "$message")
+ callback(success, message)
+ }
+ }
+
+ fun updateShareStatus(
+ diaryId: Int,
+ callback: (Boolean, String?) -> Unit
+ ) {
+ val url = "http://13.125.156.74:8080/api/diaries/$diaryId/privacy"
+
+ NetworkUtil.patchRequest(
+ url,
+ jwtToken,
+ null
+ ) { success, message ->
+ Log.d("arieum", "$message")
+ callback(success, message)
+ }
+ }
+
+ fun deleteDiary(
+ diaryId: Int,
+ callback: (Boolean, String?) -> Unit
+ ) {
+ val url = "http://13.125.156.74:8080/api/diaries/$diaryId"
+
+ NetworkUtil.deleteRequest(
+ url,
+ jwtToken,
+ null
+ ) { success, response ->
+ Log.d("arieum", "$response")
+ callback(success, response)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/repository/MemberResponse.kt b/app/src/main/java/com/example/everymoment/data/repository/MemberResponse.kt
new file mode 100644
index 0000000..511f932
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/data/repository/MemberResponse.kt
@@ -0,0 +1,14 @@
+package com.example.everymoment.data.repository
+
+data class MemberResponse(
+ val info: MemberInfo
+)
+
+data class MemberInfo(
+ val members: List
+)
+data class Member(
+ val id: Int,
+ val nickname: String,
+ val profileImageUrl: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/data/repository/UserRepository.kt b/app/src/main/java/com/example/everymoment/data/repository/UserRepository.kt
index 4d3b26e..b239650 100644
--- a/app/src/main/java/com/example/everymoment/data/repository/UserRepository.kt
+++ b/app/src/main/java/com/example/everymoment/data/repository/UserRepository.kt
@@ -1,6 +1,9 @@
package com.example.everymoment.data.repository
import android.app.Activity
+import android.util.Log
+import com.example.everymoment.GlobalApplication
+import com.example.everymoment.data.model.NetworkUtil
import com.kakao.sdk.auth.model.OAuthToken
import com.kakao.sdk.user.UserApiClient
import com.kakao.sdk.user.model.AccessTokenInfo
@@ -35,4 +38,27 @@ class UserRepository {
callback(user, error)
}
}
+
+ fun requestToken(userId: Long?, nickname: String?) {
+ NetworkUtil.sendData(
+ "http://13.125.156.74:8080/api/members/login",
+ null,
+ mapOf(
+ "number" to userId,
+ "nickname" to nickname
+ )
+ ) { success, code, message, infoObject->
+ if (success) {
+ val token = infoObject?.get("token")?.asString
+
+ if (token != null) {
+ GlobalApplication.prefs.setString("token", token)
+ }
+
+ Log.d("arieum", "서버 응답: $token")
+ } else {
+ Log.d("arieum", "Network failed")
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/extensions/CategoryPopup.kt b/app/src/main/java/com/example/everymoment/extensions/CategoryPopup.kt
index d494e8d..be4cc1c 100644
--- a/app/src/main/java/com/example/everymoment/extensions/CategoryPopup.kt
+++ b/app/src/main/java/com/example/everymoment/extensions/CategoryPopup.kt
@@ -11,8 +11,10 @@ import android.widget.ImageView
import android.widget.PopupWindow
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.DiffUtil
import com.example.everymoment.databinding.CategoryPopupBinding
import com.example.everymoment.R
+import com.example.everymoment.data.model.Friends
class CategoryPopup(
private val fragmentActivity: FragmentActivity,
@@ -111,6 +113,7 @@ class CategoryPopup(
private fun addCategoryTextView(userInput: String) {
val textView = TextView(context).apply {
+ textSize = 16f
layoutParams = GridLayout.LayoutParams().apply {
width = GridLayout.LayoutParams.WRAP_CONTENT
height = GridLayout.LayoutParams.MATCH_PARENT
@@ -139,4 +142,5 @@ class CategoryPopup(
addButton.visibility = View.GONE
}
}
+
}
diff --git a/app/src/main/java/com/example/everymoment/fcm/MyFirebaseMessagingService.kt b/app/src/main/java/com/example/everymoment/fcm/MyFirebaseMessagingService.kt
new file mode 100644
index 0000000..da82129
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/fcm/MyFirebaseMessagingService.kt
@@ -0,0 +1,113 @@
+package com.example.everymoment.fcm
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import android.widget.RemoteViews
+import androidx.core.app.NotificationCompat
+import com.example.everymoment.NotificationActionReceiver
+import com.example.everymoment.R
+import com.example.everymoment.data.model.Emotions
+import com.example.everymoment.presentation.view.main.MainActivity
+import com.google.firebase.messaging.FirebaseMessagingService
+import com.google.firebase.messaging.RemoteMessage
+
+class MyFirebaseMessagingService : FirebaseMessagingService() {
+
+ private lateinit var notificationManager: NotificationManager
+
+ override fun onNewToken(token: String) {
+ super.onNewToken(token)
+ Log.d("FCM Token", "New token: $token")
+ }
+
+ override fun onMessageReceived(remoteMessage: RemoteMessage) {
+ Log.d("testt", "From: ${remoteMessage.from}")
+
+ remoteMessage.notification?.let {
+ Log.d("testt", "Message Notification Body: ${it.body}")
+
+ notificationManager =
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ createNotificationChannel()
+ setNotification()
+ }
+ }
+
+ private fun setNotification() {
+ val intent = Intent(this, MainActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ val pendingIntent = PendingIntent.getActivity(
+ this,
+ 0,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
+
+ val remoteViews = RemoteViews(packageName, R.layout.custom_notification)
+ remoteViews.setTextViewText(R.id.happyEmojiTextView, Emotions.HAPPY.getEmotionUnicode())
+ remoteViews.setTextViewText(R.id.sadEmojiTextView, Emotions.SAD.getEmotionUnicode())
+ remoteViews.setTextViewText(R.id.insensitiveEmojiTextView, Emotions.INSENSITIVE.getEmotionUnicode())
+ remoteViews.setTextViewText(R.id.angryEmojiTextView, Emotions.ANGRY.getEmotionUnicode())
+ remoteViews.setTextViewText(R.id.confoundedEmojiTextView, Emotions.CONFOUNDED.getEmotionUnicode())
+
+ val emotions = listOf(
+ R.id.happyEmojiTextView to Emotions.HAPPY,
+ R.id.sadEmojiTextView to Emotions.SAD,
+ R.id.insensitiveEmojiTextView to Emotions.INSENSITIVE,
+ R.id.angryEmojiTextView to Emotions.ANGRY,
+ R.id.confoundedEmojiTextView to Emotions.CONFOUNDED
+ )
+
+ emotions.forEach { (viewId, emotion) ->
+ val emotionIntent = Intent(this, NotificationActionReceiver::class.java).apply {
+ action = "${emotion.name}_ACTION"
+ }
+ val emotionPendingIntent = PendingIntent.getBroadcast(
+ this,
+ viewId,
+ emotionIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ remoteViews.setOnClickPendingIntent(viewId, emotionPendingIntent)
+ }
+
+ val builder = NotificationCompat.Builder(
+ this,
+ CHANNEL_ID
+ )
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle("EveryMoment")
+ .setContentIntent(pendingIntent)
+ .setContentText("현재 XX 위치에 머무르고 있어요! 지금의 기분은 어떠신가요?")
+ .setCustomBigContentView(remoteViews)
+ .setStyle(NotificationCompat.DecoratedCustomViewStyle())
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setAutoCancel(true)
+
+ notificationManager.notify(NOTIFICATION_ID, builder.build())
+ }
+
+ private fun createNotificationChannel() {
+ val descriptionText = getString(R.string.fcm_channel_description)
+ val channel = NotificationChannel(
+ CHANNEL_ID,
+ CHANNEL_NAME,
+ NotificationManager.IMPORTANCE_DEFAULT
+ ).apply {
+ description = descriptionText
+ }
+ notificationManager.createNotificationChannel(channel)
+ }
+
+ companion object {
+ private const val NOTIFICATION_ID = 222222
+ private const val CHANNEL_ID = "main_default_channel"
+ private const val CHANNEL_NAME = "main channelName"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/CategoryAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/CategoryAdapter.kt
new file mode 100644
index 0000000..58f1d82
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/CategoryAdapter.kt
@@ -0,0 +1,60 @@
+package com.example.everymoment.presentation.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import com.example.everymoment.R
+import com.example.everymoment.databinding.CategoryLayoutBinding
+
+class CategoryAdapter() :
+ RecyclerView.Adapter() {
+
+ private var categoryList: List = listOf("#힐링", "#공부", "#놀이", "#zzzzzzz", "#ddddd", "#ee")
+ private var selectedCategories = mutableSetOf()
+
+
+ fun resetSelected() {
+ selectedCategories = mutableSetOf()
+ notifyDataSetChanged()
+ }
+
+ inner class ViewHolder(private val binding: CategoryLayoutBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(item: String, isSelected: Boolean) {
+ binding.category.text = item
+
+ if (isSelected) {
+ binding.category.setBackgroundResource(R.drawable.category_background)
+ binding.category.setTextColor(ContextCompat.getColor(itemView.context, R.color.white))
+ } else {
+ binding.category.setBackgroundResource(R.drawable.category_gray_background)
+ binding.category.setTextColor(ContextCompat.getColor(itemView.context, R.color.search_gray))
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding =
+ CategoryLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return ViewHolder(binding)
+ }
+
+ override fun getItemCount(): Int {
+ return categoryList.size
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(categoryList[position], selectedCategories.contains(position))
+
+ holder.itemView.setOnClickListener {
+ if (selectedCategories.contains(holder.adapterPosition)) {
+ selectedCategories.remove(holder.adapterPosition)
+ } else {
+ selectedCategories.add(holder.adapterPosition)
+ }
+ notifyItemChanged(holder.adapterPosition)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestAdapter.kt
index ee36a92..e141385 100644
--- a/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestAdapter.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestAdapter.kt
@@ -4,22 +4,26 @@ import android.app.AlertDialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
-import com.example.everymoment.data.model.FriendRequest
+import com.example.everymoment.data.repository.Member
import com.example.everymoment.databinding.FriendRequestItemBinding
+import com.example.everymoment.extensions.CustomDialog
class FriendRequestAdapter(
- private val onFriendRequest: (FriendRequest) -> Unit
-) : ListAdapter(
+ private val activity: FragmentActivity,
+ private val onFriendRequest: (Member) -> Unit
+) : ListAdapter(
FriendRequestDiffCallback()
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendRequestViewHolder {
val binding =
FriendRequestItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return FriendRequestViewHolder(binding, onFriendRequest)
+ return FriendRequestViewHolder(binding, activity, onFriendRequest)
}
override fun onBindViewHolder(holder: FriendRequestViewHolder, position: Int) {
@@ -28,36 +32,32 @@ class FriendRequestAdapter(
class FriendRequestViewHolder(
private val binding: FriendRequestItemBinding,
- private val onFriendRequest: (FriendRequest) -> Unit
+ private val activity: FragmentActivity,
+ private val onFriendRequest: (Member) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
- fun bind(user: FriendRequest) {
- binding.userNickname.text = user.name
+ fun bind(user: Member) {
+ binding.userNickname.text = user.nickname
binding.friendRequestButton.setOnClickListener {
showFriendRequestConfirmationDialog(user)
}
}
- private fun showFriendRequestConfirmationDialog(user: FriendRequest) {
- AlertDialog.Builder(itemView.context)
- .setTitle("친구 신청")
- .setMessage("${user.name}님에게 친구 신청을 하시겠습니까?")
- .setNegativeButton("아니오") { dialog, _ -> dialog.dismiss() }
- .setPositiveButton("네") { _, _ ->
- onFriendRequest(user)
- binding.friendRequestButton.visibility = View.GONE
- binding.requestCompletedButton.visibility = View.VISIBLE
- }
- .show()
+ private fun showFriendRequestConfirmationDialog(user: Member) {
+ CustomDialog("${user.nickname}님에게\n친구 신청을 하시겠습니까?", "아니오", "신청하기", onPositiveClick = {
+ onFriendRequest(user)
+ binding.friendRequestButton.visibility = View.GONE
+ binding.requestCompletedButton.visibility = View.VISIBLE
+ }).show(activity.supportFragmentManager, "CustomDialog")
}
}
- class FriendRequestDiffCallback : DiffUtil.ItemCallback() {
- override fun areItemsTheSame(oldItem: FriendRequest, newItem: FriendRequest): Boolean {
- return oldItem.name == newItem.name
+ class FriendRequestDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Member, newItem: Member): Boolean {
+ return oldItem.nickname == newItem.nickname
}
- override fun areContentsTheSame(oldItem: FriendRequest, newItem: FriendRequest): Boolean {
+ override fun areContentsTheSame(oldItem: Member, newItem: Member): Boolean {
return oldItem == newItem
}
}
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestListAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestListAdapter.kt
new file mode 100644
index 0000000..405ec32
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendRequestListAdapter.kt
@@ -0,0 +1,62 @@
+package com.example.everymoment.presentation.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.example.everymoment.data.model.FriendRequestList
+import com.example.everymoment.databinding.FriendRequestListItemBinding
+
+class FriendRequestListAdapter(
+ private val onFriendRequestList: (FriendRequestList) -> Unit
+) : ListAdapter(
+ FriendRequestListDiffCallback()
+) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendRequestListViewHolder {
+ val binding =
+ FriendRequestListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return FriendRequestListViewHolder(binding, onFriendRequestList)
+ }
+
+ override fun onBindViewHolder(holder: FriendRequestListViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+
+ fun removeItem(position: Int) {
+ val currentList = currentList.toMutableList()
+ currentList.removeAt(position)
+ submitList(currentList)
+ }
+
+ inner class FriendRequestListViewHolder(
+ private val binding: FriendRequestListItemBinding,
+ private val onFriendRequestList: (FriendRequestList) -> Unit
+ ) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(user: FriendRequestList) {
+ binding.userNickname.text = user.name
+
+ binding.friendRequestAcceptButton.setOnClickListener {
+ Toast.makeText(itemView.context, "${user.name}님의 친구요청을 수락했습니다.", Toast.LENGTH_SHORT).show()
+ removeItem(adapterPosition)
+ }
+
+ binding.friendRequestRefuseButton.setOnClickListener {
+ Toast.makeText(itemView.context, "${user.name}님의 친구요청을 거절했습니다.", Toast.LENGTH_SHORT).show()
+ removeItem(adapterPosition)
+ }
+ }
+ }
+
+ class FriendRequestListDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: FriendRequestList, newItem: FriendRequestList): Boolean {
+ return oldItem.name == newItem.name
+ }
+
+ override fun areContentsTheSame(oldItem: FriendRequestList, newItem: FriendRequestList): Boolean {
+ return oldItem == newItem
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/FriendsListAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendsListAdapter.kt
index 9dcadb3..d2c33d3 100644
--- a/app/src/main/java/com/example/everymoment/presentation/adapter/FriendsListAdapter.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/FriendsListAdapter.kt
@@ -3,17 +3,24 @@ package com.example.everymoment.presentation.adapter
import android.app.AlertDialog
import android.view.LayoutInflater
import android.view.ViewGroup
+import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.everymoment.data.model.Friends
import com.example.everymoment.databinding.FriendsListItemBinding
+import com.example.everymoment.extensions.CustomDialog
-class FriendsListAdapter(private val onDeleteFriend: (Friends) -> Unit) : ListAdapter(FriendDiffCallback()) {
+class FriendsListAdapter(
+ private val activity: FragmentActivity,
+ private val onDeleteFriend: (Friends) -> Unit
+) :
+ ListAdapter(FriendDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendViewHolder {
- val binding = FriendsListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return FriendViewHolder(binding, onDeleteFriend)
+ val binding =
+ FriendsListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return FriendViewHolder(binding, activity, onDeleteFriend)
}
override fun onBindViewHolder(holder: FriendViewHolder, position: Int) {
@@ -22,6 +29,7 @@ class FriendsListAdapter(private val onDeleteFriend: (Friends) -> Unit) : ListAd
class FriendViewHolder(
private val binding: FriendsListItemBinding,
+ private val activity: FragmentActivity,
private val onDeleteFriend: (Friends) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(friends: Friends) {
@@ -34,12 +42,11 @@ class FriendsListAdapter(private val onDeleteFriend: (Friends) -> Unit) : ListAd
}
private fun showDeleteConfirmationDialog(friends: Friends) {
- AlertDialog.Builder(itemView.context)
- .setTitle("친구 삭제")
- .setMessage("${friends.name}님을 친구에서 삭제하시겠습니까?")
- .setNegativeButton("아니오") { dialog, _ -> dialog.dismiss() }
- .setPositiveButton("네") { _, _ -> onDeleteFriend(friends) }
- .show()
+ CustomDialog(
+ "${friends.name}님을\n친구에서 삭제하시겠습니까?",
+ "아니오",
+ "삭제하기",
+ onPositiveClick = { onDeleteFriend(friends) }).show(activity.supportFragmentManager, "CustomDialog")
}
}
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendDiaryListAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendDiaryListAdapter.kt
new file mode 100644
index 0000000..e79aa8b
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendDiaryListAdapter.kt
@@ -0,0 +1,39 @@
+package com.example.everymoment.presentation.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.example.everymoment.data.repository.Diary
+import com.example.everymoment.databinding.ShareItemBinding
+
+class SharedFriendDiaryListAdapter : ListAdapter(
+ object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Diary, newItem: Diary): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItem: Diary, newItem: Diary): Boolean {
+ return oldItem == newItem
+ }
+ }
+) {
+ inner class ViewHolder(private val binding: ShareItemBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(item: Diary) {
+ binding.timeText.text = item.createAt
+ binding.locationNameText.text = item.locationName
+ binding.addressText.text = item.address
+
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding = ShareItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendListAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendListAdapter.kt
new file mode 100644
index 0000000..720d084
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/SharedFriendListAdapter.kt
@@ -0,0 +1,41 @@
+package com.example.everymoment.presentation.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.example.everymoment.data.repository.Member
+import com.example.everymoment.databinding.FriendItemBinding
+
+class SharedFriendListAdapter : ListAdapter(
+ object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Member, newItem: Member): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItem: Member, newItem: Member): Boolean {
+ return oldItem == newItem
+ }
+ }
+) {
+ inner class SharedFriendListViewHolder(private val binding: FriendItemBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(item: Member) {
+ binding.friendName.text = item.nickname
+ // binding.friendImage.setImageResource(item.profileImageUrl)
+
+ binding.friendContainer.setOnClickListener {
+
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SharedFriendListViewHolder {
+ val binding = FriendItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return SharedFriendListViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: SharedFriendListViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/adapter/TimelineAdapter.kt b/app/src/main/java/com/example/everymoment/presentation/adapter/TimelineAdapter.kt
index e40a260..c950e2e 100644
--- a/app/src/main/java/com/example/everymoment/presentation/adapter/TimelineAdapter.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/adapter/TimelineAdapter.kt
@@ -2,120 +2,131 @@ package com.example.everymoment.presentation.adapter
import android.content.Context
import android.view.LayoutInflater
-import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
-import androidx.core.view.isGone
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.everymoment.R
-import com.example.everymoment.data.model.Timeline
+import com.example.everymoment.data.repository.Diary
import com.example.everymoment.databinding.TimelineItemBinding
import com.example.everymoment.extensions.EmotionPopup
import com.example.everymoment.extensions.ToPxConverter
+import com.example.everymoment.presentation.viewModel.TimelineViewModel
-class TimelineAdapter(private val timelineList: MutableList): RecyclerView.Adapter() {
-
- inner class Holder(private val binding: TimelineItemBinding): RecyclerView.ViewHolder(binding.root) {
- val time = binding.timeText
- val buildingName = binding.locationNameText
- val address = binding.addressText
-
- val addEmotion = binding.addEmotion
- val emotion = binding.emotion
-
- val diaryContainer = binding.detailedDiaryContainer
-
- val editButton = binding.editIcon
- val bookmarkButton = binding.bookmarkIcon
- val shareButton = binding.shareIcon
- val deleteButton = binding.deleteIcon
- }
+class TimelineAdapter(private val viewModel: TimelineViewModel) : ListAdapter(
+ object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Diary, newItem: Diary): Boolean {
+ return oldItem.id == newItem.id
+ }
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
- val binding = TimelineItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return Holder(binding)
+ override fun areContentsTheSame(oldItem: Diary, newItem: Diary): Boolean {
+ return oldItem == newItem
+ }
}
+) {
+ inner class TimelineViewHolder(private val binding: TimelineItemBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(item: Diary) {
+ binding.timeText.text = item.createAt.substring(11, 16)
+ binding.locationNameText.text = item.locationName
+ binding.addressText.text = item.address
+
+ val emotionPopupManager = EmotionPopup(binding.root.context) { selectedEmotion ->
+ binding.emotion.text = selectedEmotion.getEmotionUnicode()
+ binding.addEmotion.visibility = View.GONE
+ binding.emotion.visibility = View.VISIBLE
+ }
- override fun getItemCount(): Int = timelineList.size
-
- override fun onBindViewHolder(holder: Holder, position: Int) {
- var isBookmarked = false
- var isShared = false
-
- holder.time.text = timelineList[position].time
- holder.buildingName.text = timelineList[position].buildingName
- holder.address.text = timelineList[position].address
+ binding.addEmotion.setOnClickListener {
+ emotionPopupManager.showEmotionsPopup(it, ToPxConverter().dpToPx(10))
+ }
- val emotionPopupManager = EmotionPopup(holder.itemView.context) { selectedEmotion ->
- holder.emotion.text = selectedEmotion.getEmotionUnicode()
- holder.addEmotion.visibility = View.GONE
- holder.emotion.visibility = View.VISIBLE
- }
+ binding.emotion.setOnClickListener {
+ emotionPopupManager.showEmotionsPopup(it, ToPxConverter().dpToPx(10))
+ }
- holder.addEmotion.setOnClickListener {
- emotionPopupManager.showEmotionsPopup(holder.addEmotion, ToPxConverter().dpToPx(10))
- }
+ var isBookmarked = item.bookmark
+ updateBookmarkIcon(isBookmarked)
- holder.emotion.setOnClickListener {
- emotionPopupManager.showEmotionsPopup(holder.emotion, ToPxConverter().dpToPx(10))
- }
+ binding.bookmarkIcon.setOnClickListener {
+ isBookmarked = !isBookmarked
+ updateBookmarkIcon(isBookmarked)
+ viewModel.updateBookmarkStatus(item.id)
+ binding.root.context.showToast(
+ if (isBookmarked) R.string.add_bookmark else R.string.remove_bookmark
+ )
+ }
- holder.bookmarkButton.setOnClickListener {
- if (isBookmarked) {
- holder.bookmarkButton.setImageResource(R.drawable.baseline_bookmark_border_24)
- holder.itemView.context.showToast(holder.itemView.context.getString(R.string.remove_bookmark))
- } else {
- holder.bookmarkButton.setImageResource(R.drawable.baseline_bookmark_24)
- holder.itemView.context.showToast(holder.itemView.context.getString(R.string.add_bookmark))
+ var isShared = item.public
+ updateShareIcon(isShared)
+
+ binding.shareIcon.setOnClickListener {
+ isShared = !isShared
+ updateShareIcon(isShared)
+ viewModel.updateShareStatus(item.id)
+ binding.root.context.showToast(
+ if (isShared) R.string.is_public else R.string.is_private
+ )
+ // SERVER : patch
}
- isBookmarked = !isBookmarked
- }
+ // 상세 일기 표시 여부
+ // binding.detailedDiaryContainer.isGone = !item.thumbnailResponse
+
+ binding.deleteIcon.setOnClickListener {
+ AlertDialog.Builder(binding.root.context)
+ .setMessage("삭제하시겠습니까?")
+ .setPositiveButton("삭제") { _, _ ->
+ removeItem(adapterPosition)
+ viewModel.deleteDiary(item.id)
+ }
+ .setNegativeButton("취소", null)
+ .show()
+ }
- holder.shareButton.setOnClickListener {
- if (isShared) {
- holder.shareButton.setImageResource(R.drawable.ic_share)
- holder.itemView.context.showToast(holder.itemView.context.getString(R.string.is_private))
- } else {
- holder.shareButton.setImageResource(R.drawable.ic_is_shared)
- holder.itemView.context.showToast(holder.itemView.context.getString(R.string.is_public))
+ binding.editIcon.setOnClickListener {
+ val popupMenu = PopupMenu(it.context, it)
+ popupMenu.menuInflater.inflate(R.menu.location_candidate_menu, popupMenu.menu)
+ popupMenu.setOnMenuItemClickListener { menuItem ->
+ binding.locationNameText.text = menuItem.title
+ true
+ }
+ popupMenu.show()
}
+ }
- isShared = !isShared
+ private fun updateBookmarkIcon(isBookmarked: Boolean) {
+ binding.bookmarkIcon.setImageResource(
+ if (isBookmarked) R.drawable.baseline_bookmark_24 else R.drawable.bookmark_26dp_5f6368_fill0_wght300_grad0_opsz24
+ )
}
- holder.diaryContainer.isGone = !timelineList[position].isDetailedDiary
+ private fun updateShareIcon(isShared: Boolean) {
+ binding.shareIcon.setImageResource(
+ if (isShared) R.drawable.ic_is_shared else R.drawable.share_26dp_5f6368_fill0_wght300_grad0_opsz24
+ )
+ }
- holder.deleteButton.setOnClickListener {
- val builder = AlertDialog.Builder(holder.itemView.context)
- builder.setMessage("삭제하시겠습니까?")
- .setPositiveButton("삭제") { dialog, id ->
- timelineList.removeAt(position)
- notifyItemRemoved(position)
- notifyItemRangeChanged(position, timelineList.size)
- }
- .setNegativeButton("취소") { dialog, id ->
- dialog.dismiss()
- }
- builder.create().show()
+ private fun removeItem(position: Int) {
+ val newList = currentList.toMutableList()
+ newList.removeAt(position)
+ submitList(newList)
}
+ }
- holder.editButton.setOnClickListener {
- val popupMenu = PopupMenu(holder.editButton.context, holder.editButton)
- popupMenu.menuInflater.inflate(R.menu.location_candidate_menu, popupMenu.menu)
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimelineViewHolder {
+ val binding = TimelineItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return TimelineViewHolder(binding)
+ }
- popupMenu.setOnMenuItemClickListener { item: MenuItem ->
- holder.buildingName.text = item.title.toString()
- true
- }
- popupMenu.show()
- }
+ override fun onBindViewHolder(holder: TimelineViewHolder, position: Int) {
+ holder.bind(getItem(position))
}
- private fun Context.showToast(message: String) {
- Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
+ private fun Context.showToast(messageResId: Int) {
+ Toast.makeText(this, getString(messageResId), Toast.LENGTH_SHORT).show()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/CalendarViewFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/CalendarViewFragment.kt
deleted file mode 100644
index 245d39f..0000000
--- a/app/src/main/java/com/example/everymoment/presentation/view/CalendarViewFragment.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.example.everymoment.presentation.view
-
-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 com.example.everymoment.R
-import com.example.everymoment.databinding.FragmentCalendarViewBinding
-import com.kakao.sdk.common.util.Utility
-
-class CalendarViewFragment : Fragment() {
-
- private lateinit var binding: FragmentCalendarViewBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentCalendarViewBinding.inflate(inflater, container, false)
- Log.d("testt", "keyhash : ${Utility.getKeyHash(requireContext())}")
- return binding.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- binding.calendarAlarm.setOnClickListener {
- requireActivity().supportFragmentManager.beginTransaction().apply {
- replace(R.id.fragment_container, NotificationFragment())
- addToBackStack(null)
- commit()
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/main/CalendarViewFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/CalendarViewFragment.kt
new file mode 100644
index 0000000..66d595a
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/CalendarViewFragment.kt
@@ -0,0 +1,68 @@
+package com.example.everymoment.presentation.view.main
+
+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 com.example.everymoment.R
+import com.example.everymoment.databinding.FragmentCalendarViewBinding
+import com.example.everymoment.presentation.view.sub.NotificationFragment
+import com.kakao.sdk.common.util.Utility
+import com.prolificinteractive.materialcalendarview.CalendarDay
+import com.prolificinteractive.materialcalendarview.MaterialCalendarView
+import com.prolificinteractive.materialcalendarview.OnDateSelectedListener
+import org.threeten.bp.format.DateTimeFormatter
+
+class CalendarViewFragment : Fragment(), OnDateSelectedListener {
+
+ private lateinit var binding: FragmentCalendarViewBinding
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentCalendarViewBinding.inflate(inflater, container, false)
+ Log.d("testt", "keyhash : ${Utility.getKeyHash(requireContext())}")
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.calendarAlarm.setOnClickListener {
+ requireActivity().supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, NotificationFragment())
+ addToBackStack(null)
+ commit()
+ }
+ }
+
+ binding.calendarView.setOnDateChangedListener(this)
+ }
+
+ override fun onDateSelected(
+ widget: MaterialCalendarView,
+ date: CalendarDay,
+ selected: Boolean
+ ) {
+ if (selected) {
+ // 선택된 날짜를 원하는 형식으로 포맷팅
+ val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
+ val formattedDate = date.date.format(formatter)
+
+ // TodayLogFragment로 이동하면서 선택한 날짜 전달
+ val todayLogFragment = TodayLogFragment().apply {
+ arguments = Bundle().apply {
+ putString("selected_date", formattedDate)
+ }
+ }
+
+ requireActivity().supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, todayLogFragment)
+ addToBackStack(null)
+ commit()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/KakaoLoginActivity.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/KakaoLoginActivity.kt
similarity index 97%
rename from app/src/main/java/com/example/everymoment/presentation/view/KakaoLoginActivity.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/main/KakaoLoginActivity.kt
index 99fbd59..688252b 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/KakaoLoginActivity.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/KakaoLoginActivity.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.main
import android.content.Intent
import android.os.Bundle
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/MainActivity.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/MainActivity.kt
similarity index 67%
rename from app/src/main/java/com/example/everymoment/presentation/view/MainActivity.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/main/MainActivity.kt
index 19774f2..a729582 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/MainActivity.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/MainActivity.kt
@@ -1,10 +1,16 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.main
import android.os.Bundle
+import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.example.everymoment.R
import com.example.everymoment.databinding.ActivityMainBinding
+import com.example.everymoment.presentation.view.main.search.SearchFragment
+import com.google.firebase.ktx.Firebase
+import com.google.firebase.remoteconfig.FirebaseRemoteConfig
+import com.google.firebase.remoteconfig.ktx.remoteConfig
+import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
@@ -14,6 +20,13 @@ class MainActivity : AppCompatActivity() {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
+ val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
+ val configSettings = remoteConfigSettings {
+ minimumFetchIntervalInSeconds = 0
+ }
+ remoteConfig.setConfigSettingsAsync(configSettings)
+ fetchValues()
+
if (savedInstanceState == null) {
val fragment = TodayLogFragment()
supportFragmentManager.beginTransaction()
@@ -32,6 +45,22 @@ class MainActivity : AppCompatActivity() {
binding.bottomNavigationView.visibility = View.VISIBLE
}
+ private fun fetchValues() {
+ Firebase.remoteConfig.fetchAndActivate().addOnCompleteListener {
+ if (it.isSuccessful) {
+ val serviceState = Firebase.remoteConfig.getString("serviceState")
+ val serviceMessage = Firebase.remoteConfig.getString("serviceMessage")
+ Log.d("testt", "state: $serviceState")
+ Log.d("testt", "serviceMessage: $serviceMessage")
+ if (serviceState == "ON_SERVICE") {
+ Log.d("testt", "온서비스")
+ } else {
+ Log.d("testt", "온서비스아님")
+ }
+ }
+ }
+ }
+
private fun initNavigationBar() {
binding.bottomNavigationView.run {
@@ -46,7 +75,7 @@ class MainActivity : AppCompatActivity() {
}
R.id.feed -> {
- val fragment = PostFragment()
+ val fragment = ShareViewFragment()
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit()
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/SettingFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/SettingFragment.kt
similarity index 85%
rename from app/src/main/java/com/example/everymoment/presentation/view/SettingFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/main/SettingFragment.kt
index 1271f04..6f0dea7 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/SettingFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/SettingFragment.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.main
import android.net.Uri
import android.os.Bundle
@@ -13,7 +13,6 @@ import com.example.everymoment.databinding.FragmentSettingBinding
import com.example.everymoment.extensions.CustomDialog
import com.example.everymoment.extensions.CustomEditDialog
import com.example.everymoment.extensions.GalleryUtil
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
class SettingFragment : Fragment() {
@@ -50,17 +49,33 @@ class SettingFragment : Fragment() {
profileNameDialog.show(requireActivity().supportFragmentManager, "CustomDialog")
}
- binding.notificationToggle.setOnCheckedChangeListener { _, isChecked ->
+ binding.autoNotificationToggle.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
Toast.makeText(
requireContext(),
- resources.getString(R.string.notification_isChecked),
+ resources.getString(R.string.auto_notification_isChecked),
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
requireContext(),
- resources.getString(R.string.notification_isUnChecked),
+ resources.getString(R.string.auto_notification_isUnChecked),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+
+ binding.pushNotificationToggle.setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked) {
+ Toast.makeText(
+ requireContext(),
+ resources.getString(R.string.push_notification_isChecked),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ Toast.makeText(
+ requireContext(),
+ resources.getString(R.string.push_notification_isUnChecked),
Toast.LENGTH_SHORT
).show()
}
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/main/ShareViewFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/ShareViewFragment.kt
new file mode 100644
index 0000000..b58f805
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/ShareViewFragment.kt
@@ -0,0 +1,69 @@
+package com.example.everymoment.presentation.view.main
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.example.everymoment.R
+import com.example.everymoment.data.repository.Diary
+import com.example.everymoment.data.repository.Member
+import com.example.everymoment.data.repository.Thumbnail
+import com.example.everymoment.databinding.FragmentShareViewBinding
+import com.example.everymoment.presentation.adapter.SharedFriendDiaryListAdapter
+import com.example.everymoment.presentation.adapter.SharedFriendListAdapter
+import com.example.everymoment.presentation.view.sub.friends.FriendsListFragment
+
+class ShareViewFragment : Fragment() {
+ private lateinit var binding: FragmentShareViewBinding
+
+ private val friendAdapter = SharedFriendListAdapter()
+ private val diaryAdapter = SharedFriendDiaryListAdapter()
+ private var friendList: MutableList = mutableListOf()
+ private var diaryList: MutableList = mutableListOf()
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentShareViewBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setupRecyclerView()
+
+ // dummyData1
+ friendList.add(Member(1, "url", "춘식이"))
+ friendList.add(Member(2, "url", "제이지"))
+ friendList.add(Member(3, "url", "프로도"))
+ friendList.add(Member(4, "url", "네오"))
+ friendList.add(Member(5, "url", "피치"))
+ friendAdapter.submitList(friendList)
+ friendAdapter.notifyDataSetChanged()
+
+ // dummyData2
+ diaryList.add(Diary(1, "춘천 한림대", "강원도 춘천시", "Happy", Thumbnail(1, "url"), "Hello", "2024-05-06", false, true))
+ diaryList.add(Diary(2, "춘천 강원대", "강원도 춘천시", "Happy", Thumbnail(1, "url"), "Hello", "2024-05-06", false, true))
+ diaryAdapter.submitList(diaryList)
+ diaryAdapter.notifyDataSetChanged()
+
+ binding.friendListIcon.setOnClickListener {
+ requireActivity().supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, FriendsListFragment())
+ addToBackStack(null)
+ commit()
+ }
+ }
+ }
+
+ private fun setupRecyclerView() {
+ binding.friendList.adapter = friendAdapter
+ binding.timeLineRecyclerView.adapter = diaryAdapter
+
+ binding.friendList.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
+ binding.timeLineRecyclerView.layoutManager = LinearLayoutManager(requireContext())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/TodayLogFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/TodayLogFragment.kt
similarity index 67%
rename from app/src/main/java/com/example/everymoment/presentation/view/TodayLogFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/main/TodayLogFragment.kt
index 5acf6ec..8dc0d98 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/TodayLogFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/TodayLogFragment.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.main
import android.content.Intent
import android.os.Build
@@ -6,17 +6,25 @@ import android.os.Bundle
import androidx.core.content.ContextCompat
import android.Manifest
import android.content.pm.PackageManager
+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.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.everymoment.LocationService
import com.example.everymoment.R
-import com.example.everymoment.data.model.Timeline
+import com.example.everymoment.data.repository.DiaryRepository
import com.example.everymoment.databinding.FragmentTodayLogBinding
import com.example.everymoment.presentation.adapter.TimelineAdapter
+import com.example.everymoment.presentation.view.sub.NotificationFragment
+import com.example.everymoment.presentation.viewModel.TimelineViewModel
+import com.example.everymoment.presentation.viewModel.TimelineViewModelFactory
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
class TodayLogFragment : Fragment() {
@@ -38,7 +46,9 @@ class TodayLogFragment : Fragment() {
}
private lateinit var binding: FragmentTodayLogBinding
-
+ private lateinit var viewModel: TimelineViewModel
+ private val diaryRepository = DiaryRepository()
+ private val calendar = Calendar.getInstance()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -50,16 +60,52 @@ class TodayLogFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val timelineList: MutableList = mutableListOf()
- // 리스트 예시
- timelineList.add(Timeline("오전 10:00", "빽다방 강원대점", "강원도 춘천시 충열로", "😢", true))
- timelineList.add(Timeline("오후 12:00", "천지관", "강원도 춘천시 충열로", "😢", false))
+ viewModel = ViewModelProvider(this, TimelineViewModelFactory(diaryRepository)).get(
+ TimelineViewModel::class.java
+ )
+
+ val TodayDate = arguments?.getString("selected_date")
+ Log.d("TodayDate", "Selected date: $TodayDate")
checkPermissions()
- setupRecyclerView(timelineList)
+ updateDateText()
+
+ val adapter = TimelineAdapter(viewModel)
+ setupRecyclerView(adapter)
+ observeViewModel(adapter)
+
+ val initialDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ viewModel.fetchDiaries(initialDate)
+
binding.notification.setOnClickListener {
navigateToNotificationFragment()
}
+
+ binding.nextDate.setOnClickListener {
+ calendar.add(Calendar.DATE, 1)
+ updateDateText()
+ val currentDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+ viewModel.fetchDiaries(currentDate)
+ }
+
+ binding.prevDate.setOnClickListener {
+ calendar.add(Calendar.DATE, -1)
+ updateDateText()
+ val currentDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+ viewModel.fetchDiaries(currentDate)
+ }
+ }
+
+ private fun observeViewModel(adapter: TimelineAdapter) {
+ viewModel.diaries.observe(viewLifecycleOwner) { diaryList ->
+ adapter.submitList(diaryList)
+ }
+ }
+
+ private fun updateDateText() {
+ val formattedDate = SimpleDateFormat("M월 d일 (E)", Locale("ko", "KR")).format(calendar.time)
+ binding.currentDate.text = formattedDate
}
private fun navigateToNotificationFragment() {
@@ -70,8 +116,8 @@ class TodayLogFragment : Fragment() {
}
}
- private fun setupRecyclerView(timelineList: MutableList) {
- binding.timeLineRecyclerView.adapter = TimelineAdapter(timelineList)
+ private fun setupRecyclerView(adapter: TimelineAdapter) {
+ binding.timeLineRecyclerView.adapter = adapter
binding.timeLineRecyclerView.layoutManager = LinearLayoutManager(requireContext())
}
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFilterDialogFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFilterDialogFragment.kt
new file mode 100644
index 0000000..6ccda0b
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFilterDialogFragment.kt
@@ -0,0 +1,203 @@
+package com.example.everymoment.presentation.view.main.search
+
+import android.app.DatePickerDialog
+import android.icu.util.Calendar
+import android.os.Build
+import android.os.Bundle
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.GridLayout
+import android.widget.TextView
+import android.widget.Toast
+import androidx.annotation.RequiresApi
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.GridLayoutManager
+import com.example.everymoment.R
+import com.example.everymoment.data.model.Emotions
+import com.example.everymoment.databinding.FragmentSearchFilterDialogBinding
+import com.example.everymoment.presentation.adapter.CategoryAdapter
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+
+class SearchFilterDialogFragment : BottomSheetDialogFragment() {
+
+ private lateinit var binding: FragmentSearchFilterDialogBinding
+ private lateinit var categoryAdapter: CategoryAdapter
+ private var checkedBookmark: Boolean = false
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentSearchFilterDialogBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ val bottomSheetBehavior = BottomSheetBehavior.from(view.parent as View)
+ bottomSheetBehavior.isDraggable = false
+
+ setEmoji()
+ setCategories()
+
+ binding.bookmark.setOnClickListener {
+ if (!checkedBookmark) {
+ binding.bookmarkIcon.setImageResource(R.drawable.baseline_bookmark_24)
+ binding.bookmarkDesc.setTextColor(
+ ContextCompat.getColor(
+ requireContext(),
+ R.color.primary_color
+ )
+ )
+ } else {
+ binding.bookmarkIcon.setImageResource(R.drawable.gray_border_bookmark)
+ binding.bookmarkDesc.setTextColor(
+ ContextCompat.getColor(
+ requireContext(),
+ R.color.search_gray
+ )
+ )
+ }
+ checkedBookmark = !checkedBookmark
+ }
+
+ binding.startDate.setOnClickListener {
+ showCalendarDialog(binding.startDate) {
+ if (binding.startDate.text.isNotEmpty()) {
+ binding.startDate.setBackgroundResource(R.drawable.search_filter_date_background)
+ }}
+ }
+
+ binding.endDate.setOnClickListener {
+ showCalendarDialog(binding.endDate) {
+ if (binding.endDate.text.isNotEmpty()) {
+ binding.endDate.setBackgroundResource(R.drawable.search_filter_date_background)
+ }}
+ }
+
+ binding.reset.setOnClickListener {
+ resetSelections()
+ }
+
+ binding.apply.setOnClickListener {
+ if (binding.startDate.text.isNullOrEmpty() && binding.endDate.text.isNotEmpty()) {
+ makeToast(resources.getString(R.string.check_start_date))
+ } else if (binding.startDate.text.isNotEmpty() && binding.endDate.text.isNullOrEmpty()) {
+ makeToast(resources.getString(R.string.check_end_date))
+ } else if (binding.startDate.text.isNotEmpty() && binding.endDate.text.isNotEmpty()) {
+ if (!checkValidTerm()) {
+ makeToast(resources.getString(R.string.invalid_term))
+ }
+ } else {
+ dismiss()
+ }
+ }
+
+ }
+
+ private fun makeToast(string: String) {
+ Toast.makeText(
+ context,
+ string,
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ private fun setCategories() {
+ val gridLayoutManager = GridLayoutManager(requireContext(), 3)
+ binding.categoryRcv.layoutManager = gridLayoutManager
+ categoryAdapter = CategoryAdapter()
+ binding.categoryRcv.adapter = categoryAdapter
+
+ if (categoryAdapter.itemCount != 0) {
+ binding.noCategoryText.visibility = View.GONE
+ binding.categoryRcv.visibility = View.VISIBLE
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun String.toLocalDate(): LocalDate {
+ val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
+ return LocalDate.parse(this, formatter)
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun checkValidTerm(): Boolean {
+ val startDate = binding.startDate.text.toString().toLocalDate()
+ val endDate = binding.endDate.text.toString().toLocalDate()
+ return !startDate.isAfter(endDate)
+ }
+
+ private fun resetSelections() {
+ checkedBookmark = false
+ binding.bookmarkIcon.setImageResource(R.drawable.gray_border_bookmark)
+ binding.bookmarkDesc.setTextColor(
+ ContextCompat.getColor(
+ requireContext(),
+ R.color.search_gray
+ )
+ )
+
+ binding.happy.isChecked = false
+ binding.sad.isChecked = false
+ binding.insensitive.isChecked = false
+ binding.angry.isChecked = false
+ binding.confounded.isChecked = false
+
+ binding.startDate.text = ""
+ binding.startDate.setBackgroundResource(R.drawable.search_filter_date_gray_background)
+ binding.endDate.text = ""
+ binding.endDate.setBackgroundResource(R.drawable.search_filter_date_gray_background)
+
+ categoryAdapter.resetSelected()
+ }
+
+ private fun changeDateBackground(input: ()->Unit) {
+ input.invoke()
+ }
+
+ private fun showCalendarDialog(textView: TextView, checkInput: ()->Unit) {
+ val calendar = Calendar.getInstance()
+ val year = calendar.get(Calendar.YEAR)
+ val month = calendar.get(Calendar.MONTH)
+ val day = calendar.get(Calendar.DAY_OF_MONTH)
+ context?.let { context ->
+ DatePickerDialog(context, R.style.CustomDatePicker, { _, selectedYear, selectedMonth, selectedDay ->
+ val formattedDate =
+ String.format("%04d.%02d.%02d", selectedYear, selectedMonth + 1, selectedDay)
+ textView.text = formattedDate
+ changeDateBackground(checkInput)
+ }, year, month, day).show()
+ }
+ }
+
+ private fun setEmoji() {
+ binding.happy.text = Emotions.HAPPY.getEmotionUnicode()
+ binding.happy.textOn = Emotions.HAPPY.getEmotionUnicode()
+ binding.happy.textOff = Emotions.HAPPY.getEmotionUnicode()
+ binding.sad.text = Emotions.SAD.getEmotionUnicode()
+ binding.sad.textOn = Emotions.SAD.getEmotionUnicode()
+ binding.sad.textOff = Emotions.SAD.getEmotionUnicode()
+ binding.insensitive.text = Emotions.INSENSITIVE.getEmotionUnicode()
+ binding.insensitive.textOn = Emotions.INSENSITIVE.getEmotionUnicode()
+ binding.insensitive.textOff = Emotions.INSENSITIVE.getEmotionUnicode()
+ binding.angry.text = Emotions.ANGRY.getEmotionUnicode()
+ binding.angry.textOn = Emotions.ANGRY.getEmotionUnicode()
+ binding.angry.textOff = Emotions.ANGRY.getEmotionUnicode()
+ binding.confounded.text = Emotions.CONFOUNDED.getEmotionUnicode()
+ binding.confounded.textOn = Emotions.CONFOUNDED.getEmotionUnicode()
+ binding.confounded.textOff = Emotions.CONFOUNDED.getEmotionUnicode()
+ }
+
+ companion object {
+ const val TAG = "SearchFilterBottomSheet"
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/SearchFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFragment.kt
similarity index 78%
rename from app/src/main/java/com/example/everymoment/presentation/view/SearchFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFragment.kt
index e9c4b8b..0c494d3 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/SearchFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/main/search/SearchFragment.kt
@@ -1,16 +1,16 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.main.search
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import com.example.everymoment.R
import com.example.everymoment.databinding.FragmentSearchBinding
class SearchFragment : Fragment() {
private lateinit var binding: FragmentSearchBinding
+ private lateinit var filterBottomSheet: SearchFilterDialogFragment
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@@ -34,11 +34,11 @@ class SearchFragment : Fragment() {
}
private fun setFilterSheet() {
-
+ filterBottomSheet = SearchFilterDialogFragment()
}
private fun showFilterSheet() {
-
+ filterBottomSheet.show(parentFragmentManager, SearchFilterDialogFragment.TAG)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/NotificationFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/NotificationFragment.kt
similarity index 94%
rename from app/src/main/java/com/example/everymoment/presentation/view/NotificationFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/NotificationFragment.kt
index 0b38dab..efb6c55 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/NotificationFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/NotificationFragment.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub
import android.os.Bundle
import androidx.fragment.app.Fragment
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/PostFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/PostFragment.kt
similarity index 96%
rename from app/src/main/java/com/example/everymoment/presentation/view/PostFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/PostFragment.kt
index bbec736..b047f9c 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/PostFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/PostFragment.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub
import android.content.Context
import android.os.Bundle
@@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.recyclerview.widget.LinearLayoutManager
-import com.example.everymoment.R
import com.example.everymoment.databinding.FragmentPostBinding
import com.example.everymoment.presentation.adapter.PostAdapter
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/DiaryEditFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryEditFragment.kt
similarity index 90%
rename from app/src/main/java/com/example/everymoment/presentation/view/DiaryEditFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryEditFragment.kt
index fac7fa7..bb5a8a8 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/DiaryEditFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryEditFragment.kt
@@ -1,16 +1,18 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub.diary
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.ImageView
import com.example.everymoment.databinding.FragmentDiaryEditBinding
import com.example.everymoment.extensions.Bookmarks
import com.example.everymoment.extensions.CategoryPopup
import com.example.everymoment.extensions.EmotionPopup
import com.example.everymoment.extensions.GalleryUtil
import com.example.everymoment.extensions.ToPxConverter
+import com.example.everymoment.presentation.view.main.MainActivity
class DiaryEditFragment : Fragment() {
@@ -52,16 +54,19 @@ class DiaryEditFragment : Fragment() {
binding.image1.setOnClickListener {
galleryUtil.openGallery(onImageSelected = {
+ binding.image1.scaleType = ImageView.ScaleType.CENTER_CROP
binding.image1.setImageURI(it)
+ imagesArray[0] = true
+ binding.image2.visibility = View.VISIBLE
})
- imagesArray[0] = true
}
binding.image2.setOnClickListener {
galleryUtil.openGallery(onImageSelected = {
+ binding.image2.scaleType = ImageView.ScaleType.CENTER_CROP
binding.image2.setImageURI(it)
+ imagesArray[1] = true
})
- imagesArray[1] = true
}
binding.addCategory.setOnClickListener {
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/DiaryReadFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryReadFragment.kt
similarity index 95%
rename from app/src/main/java/com/example/everymoment/presentation/view/DiaryReadFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryReadFragment.kt
index 6d6eca2..e679f3d 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/DiaryReadFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/diary/DiaryReadFragment.kt
@@ -1,4 +1,4 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub.diary
import android.os.Bundle
import androidx.fragment.app.Fragment
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/FriendRequestFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestFragment.kt
similarity index 55%
rename from app/src/main/java/com/example/everymoment/presentation/view/FriendRequestFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestFragment.kt
index 817424b..e754508 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/FriendRequestFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestFragment.kt
@@ -1,6 +1,7 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub.friends
import android.os.Bundle
+import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
@@ -8,8 +9,9 @@ import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.everymoment.R
-import com.example.everymoment.data.model.FriendRequest
-import com.example.everymoment.data.model.Friends
+import com.example.everymoment.data.model.NetworkUtil
+import com.example.everymoment.data.repository.Member
+import com.example.everymoment.data.repository.MemberResponse
import com.example.everymoment.databinding.FragmentFriendRequestBinding
import com.example.everymoment.presentation.adapter.FriendRequestAdapter
@@ -19,19 +21,8 @@ class FriendRequestFragment : Fragment() {
private lateinit var adapter: FriendRequestAdapter
// 테스트용 더미 데이터
- private val allUsers = mutableListOf(
- FriendRequest("박지연", "https://example.com/user1.jpg"),
- FriendRequest("한예지", "https://example.com/user2.jpg"),
- FriendRequest("춘식이", "https://example.com/user3.jpg"),
- FriendRequest("소연이", "https://example.com/user4.jpg"),
- FriendRequest("박소담", "https://example.com/user5.jpg"),
- FriendRequest("한가인", "https://example.com/user6.jpg"),
- FriendRequest("박지승", "https://example.com/user7.jpg"),
- FriendRequest("김고은", "https://example.com/user8.jpg"),
- FriendRequest("박소영", "https://example.com/user9.jpg"),
- FriendRequest("김범수", "https://example.com/user10.jpg"),
- FriendRequest("한혜진", "https://example.com/user11.jpg")
- )
+ private var allMembers = mutableListOf()
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@@ -46,6 +37,7 @@ class FriendRequestFragment : Fragment() {
setupRecyclerView()
setupSearch()
+ fetchMembersFromServer()
binding.friendsBackButton.setOnClickListener {
requireActivity().supportFragmentManager.beginTransaction().apply {
@@ -54,20 +46,52 @@ class FriendRequestFragment : Fragment() {
commit()
}
}
+
+ }
+
+ private fun fetchMembersFromServer() {
+ val url = "http://13.125.156.74:8080/api/members?size=30"
+ val jwtToken =
+ "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6NiwiaWF0IjoxNzI4NjA5ODk3LCJleHAiOjE3Mjg3ODI2OTd9.JaJ2Ut7M_YePTXZZNODRu6eGBXwbO2kLtDXl2jz9Ock"
+
+ NetworkUtil.getData(
+ url,
+ jwtToken,
+ responseClass = MemberResponse::class.java
+ ) { success, memberResponse ->
+ if (success && memberResponse != null) {
+ Log.d("memberNetwork", "fetchedMemberList : ${memberResponse.info.members}")
+
+ allMembers.clear()
+ allMembers.addAll(memberResponse.info.members)
+ Log.d("memberNetwork", "allMembers list: $allMembers")
+
+ activity?.runOnUiThread {
+ adapter.submitList(allMembers)
+ setupRecyclerView()
+ }
+ } else {
+ Log.d("memberNetwork", "Network failed")
+ activity?.runOnUiThread {
+
+ }
+ }
+ }
}
private fun setupRecyclerView() {
- adapter = FriendRequestAdapter { user ->
+ adapter = FriendRequestAdapter (requireActivity()) { user ->
}
binding.friendRequestRecyclerView.layoutManager = LinearLayoutManager(requireContext())
binding.friendRequestRecyclerView.adapter = adapter
- adapter.submitList(allUsers)
+ adapter.submitList(allMembers)
}
private fun setupSearch() {
binding.searchUserEditText.addTextChangedListener { editable ->
val searchText = editable.toString()
- val filteredList = allUsers.filter { it.name.contains(searchText, ignoreCase = true) }
+ val filteredList =
+ allMembers.filter { it.nickname.contains(searchText, ignoreCase = true) }
adapter.submitList(filteredList)
if (filteredList.isEmpty()) {
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestListFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestListFragment.kt
new file mode 100644
index 0000000..add884e
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendRequestListFragment.kt
@@ -0,0 +1,64 @@
+package com.example.everymoment.presentation.view.sub.friends
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.example.everymoment.R
+import com.example.everymoment.data.model.FriendRequestList
+import com.example.everymoment.databinding.FragmentFriendRequestListBinding
+import com.example.everymoment.presentation.adapter.FriendRequestListAdapter
+
+
+class FriendRequestListFragment : Fragment() {
+
+ // 테스트용 더미 데이터
+ private val friendRequestMember = mutableListOf(
+ FriendRequestList("박지연", "https://example.com/user1.jpg"),
+ FriendRequestList("한예지", "https://example.com/user2.jpg"),
+ FriendRequestList("춘식이", "https://example.com/user3.jpg"),
+ FriendRequestList("소연이", "https://example.com/user4.jpg"),
+ FriendRequestList("박소담", "https://example.com/user5.jpg"),
+ FriendRequestList("한가인", "https://example.com/user6.jpg"),
+ FriendRequestList("박지승", "https://example.com/user7.jpg"),
+ FriendRequestList("김고은", "https://example.com/user8.jpg"),
+ FriendRequestList("박소영", "https://example.com/user9.jpg"),
+ FriendRequestList("김범수", "https://example.com/user10.jpg"),
+ FriendRequestList("한혜진", "https://example.com/user11.jpg")
+ )
+
+ private lateinit var binding: FragmentFriendRequestListBinding
+ private lateinit var adapter: FriendRequestListAdapter
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentFriendRequestListBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ setupRecyclerView()
+
+ binding.friendRequestListBackButton.setOnClickListener {
+ requireActivity().supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, FriendsListFragment())
+ addToBackStack(null)
+ commit()
+ }
+ }
+ }
+
+ private fun setupRecyclerView() {
+ adapter = FriendRequestListAdapter { friendRequest ->
+ }
+ binding.friendRequestListRecyclerView.layoutManager = LinearLayoutManager(requireContext())
+ binding.friendRequestListRecyclerView.adapter = adapter
+ adapter.submitList(friendRequestMember.toList())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/view/FriendsListFragment.kt b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendsListFragment.kt
similarity index 52%
rename from app/src/main/java/com/example/everymoment/presentation/view/FriendsListFragment.kt
rename to app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendsListFragment.kt
index 60159f6..0607c37 100644
--- a/app/src/main/java/com/example/everymoment/presentation/view/FriendsListFragment.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/view/sub/friends/FriendsListFragment.kt
@@ -1,9 +1,11 @@
-package com.example.everymoment.presentation.view
+package com.example.everymoment.presentation.view.sub.friends
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.animation.Animation
+import android.view.animation.AnimationUtils
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
@@ -16,6 +18,23 @@ class FriendsListFragment : Fragment() {
private lateinit var binding: FragmentFriendsListBinding
private lateinit var adapter: FriendsListAdapter
+ private var isFabExpanded = false
+
+ private val fromBottomFabAnim : Animation by lazy {
+ AnimationUtils.loadAnimation(requireContext(), R.anim.from_bottom_fab)
+ }
+
+ private val toBottomFabAnim : Animation by lazy {
+ AnimationUtils.loadAnimation(requireContext(), R.anim.to_bottom_fab)
+ }
+
+ private val rotateClockWiseFabAnim : Animation by lazy {
+ AnimationUtils.loadAnimation(requireContext(), R.anim.rotate_clock_wise)
+ }
+
+ private val rotateAntiClockWiseFabAnim : Animation by lazy {
+ AnimationUtils.loadAnimation(requireContext(), R.anim.rotate_anti_clock_wise)
+ }
// 테스트용 더미 데이터
private val friendsList = mutableListOf(
@@ -43,20 +62,73 @@ class FriendsListFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- setupRecyclerView()
- setupSearch()
+ binding.mainFab.setOnClickListener {
+ if (isFabExpanded) {
+ shrinkFab()
+ } else {
+ expandFab()
+ }
+ }
- binding.friendAddButton.setOnClickListener {
+ binding.friendRequestFab.setOnClickListener {
requireActivity().supportFragmentManager.beginTransaction().apply {
replace(R.id.fragment_container, FriendRequestFragment())
addToBackStack(null)
commit()
}
}
+
+ binding.friendAcceptFab.setOnClickListener {
+ requireActivity().supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, FriendRequestListFragment())
+ addToBackStack(null)
+ commit()
+ }
+ }
+
+ setupRecyclerView()
+ setupSearch()
+
+
+ }
+
+ private fun expandFab() {
+
+ binding.mainFab.startAnimation(rotateClockWiseFabAnim)
+ binding.friendRequestFab.startAnimation(fromBottomFabAnim)
+ binding.friendAcceptFab.startAnimation(fromBottomFabAnim)
+ binding.friendRequestFabTv.startAnimation(fromBottomFabAnim)
+ binding.friendAcceptFabTv.startAnimation(fromBottomFabAnim)
+
+ binding.friendRequestFabTv.visibility = View.VISIBLE
+ binding.friendAcceptFabTv.visibility = View.VISIBLE
+ binding.friendRequestFab.visibility = View.VISIBLE
+ binding.friendRequestFab.isClickable = true
+ binding.friendAcceptFab.visibility = View.VISIBLE
+ binding.friendAcceptFab.isClickable = true
+ isFabExpanded = !isFabExpanded
+ }
+
+ private fun shrinkFab() {
+
+ binding.mainFab.startAnimation(rotateAntiClockWiseFabAnim)
+ binding.friendRequestFab.startAnimation(toBottomFabAnim)
+ binding.friendAcceptFab.startAnimation(toBottomFabAnim)
+ binding.friendRequestFabTv.startAnimation(toBottomFabAnim)
+ binding.friendAcceptFabTv.startAnimation(toBottomFabAnim)
+
+ binding.friendRequestFabTv.visibility = View.GONE
+ binding.friendAcceptFabTv.visibility = View.GONE
+ binding.friendRequestFab.visibility = View.GONE
+ binding.friendRequestFab.isClickable = false
+ binding.friendAcceptFab.visibility = View.GONE
+ binding.friendAcceptFab.isClickable = false
+
+ isFabExpanded = !isFabExpanded
}
private fun setupRecyclerView() {
- adapter = FriendsListAdapter { friend ->
+ adapter = FriendsListAdapter(requireActivity()) { friend ->
deleteFriend(friend)
}
binding.friendsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
diff --git a/app/src/main/java/com/example/everymoment/presentation/viewModel/KakaoLoginViewModel.kt b/app/src/main/java/com/example/everymoment/presentation/viewModel/KakaoLoginViewModel.kt
index 17778eb..cff13f2 100644
--- a/app/src/main/java/com/example/everymoment/presentation/viewModel/KakaoLoginViewModel.kt
+++ b/app/src/main/java/com/example/everymoment/presentation/viewModel/KakaoLoginViewModel.kt
@@ -56,6 +56,7 @@ class KakaoLoginViewModel(private val userRepository: UserRepository) : ViewMode
"\n회원번호: ${user.id}" +
"\n닉네임: ${user.kakaoAccount?.profile?.nickname}"
)
+ userRepository.requestToken(user.id, user.kakaoAccount?.profile?.nickname)
_uiState.value = KakaoLoginUiState(
isLoggedIn = true,
userId = user.id,
diff --git a/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModel.kt b/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModel.kt
new file mode 100644
index 0000000..7ba71fe
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModel.kt
@@ -0,0 +1,45 @@
+package com.example.everymoment.presentation.viewModel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.everymoment.data.repository.Diary
+import com.example.everymoment.data.repository.DiaryRepository
+import kotlinx.coroutines.launch
+
+class TimelineViewModel(private val diaryRepository: DiaryRepository) : ViewModel() {
+ private val _diaries = MutableLiveData>()
+ val diaries: LiveData> get() = _diaries
+
+
+ fun fetchDiaries(date: String) {
+ viewModelScope.launch {
+ diaryRepository.getDiaries(date) { success, response ->
+ if (success && response != null) {
+ _diaries.postValue(response.info.diaries)
+ }
+ }
+ }
+ }
+
+ fun updateBookmarkStatus(diaryId: Int) {
+ viewModelScope.launch {
+ diaryRepository.updateBookmarkStatus(diaryId) { success, response ->
+ }
+ }
+ }
+
+ fun updateShareStatus(diaryId: Int) {
+ viewModelScope.launch {
+ diaryRepository.updateShareStatus(diaryId) { success, response ->
+ }
+ }
+ }
+
+ fun deleteDiary(diaryId: Int){
+ viewModelScope.launch {
+ diaryRepository.deleteDiary(diaryId) { success, response -> }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModelFactory.kt b/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModelFactory.kt
new file mode 100644
index 0000000..956ba56
--- /dev/null
+++ b/app/src/main/java/com/example/everymoment/presentation/viewModel/TimelineViewModelFactory.kt
@@ -0,0 +1,16 @@
+package com.example.everymoment.presentation.viewModel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.example.everymoment.data.repository.DiaryRepository
+
+class TimelineViewModelFactory(
+ private val diaryRepository: DiaryRepository
+) : ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(TimelineViewModel::class.java)) {
+ return TimelineViewModel(diaryRepository) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/anim/from_bottom_fab.xml b/app/src/main/res/anim/from_bottom_fab.xml
new file mode 100644
index 0000000..b318ef3
--- /dev/null
+++ b/app/src/main/res/anim/from_bottom_fab.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/rotate_anti_clock_wise.xml b/app/src/main/res/anim/rotate_anti_clock_wise.xml
new file mode 100644
index 0000000..b1a6131
--- /dev/null
+++ b/app/src/main/res/anim/rotate_anti_clock_wise.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/rotate_clock_wise.xml b/app/src/main/res/anim/rotate_clock_wise.xml
new file mode 100644
index 0000000..4ab4805
--- /dev/null
+++ b/app/src/main/res/anim/rotate_clock_wise.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/to_bottom_fab.xml b/app/src/main/res/anim/to_bottom_fab.xml
new file mode 100644
index 0000000..d73d5ef
--- /dev/null
+++ b/app/src/main/res/anim/to_bottom_fab.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/add_24px.xml b/app/src/main/res/drawable/add_24px.xml
new file mode 100644
index 0000000..76c2d3c
--- /dev/null
+++ b/app/src/main/res/drawable/add_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/bookmark_26dp_5f6368_fill0_wght300_grad0_opsz24.xml b/app/src/main/res/drawable/bookmark_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
new file mode 100644
index 0000000..7ea34ef
--- /dev/null
+++ b/app/src/main/res/drawable/bookmark_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/category_gray_background.xml b/app/src/main/res/drawable/category_gray_background.xml
new file mode 100644
index 0000000..14bc8f7
--- /dev/null
+++ b/app/src/main/res/drawable/category_gray_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/delete_26dp_5f6368_fill0_wght300_grad0_opsz24.xml b/app/src/main/res/drawable/delete_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
new file mode 100644
index 0000000..e4dd795
--- /dev/null
+++ b/app/src/main/res/drawable/delete_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/emoji_selected_circle.xml b/app/src/main/res/drawable/emoji_selected_circle.xml
new file mode 100644
index 0000000..3d45ef6
--- /dev/null
+++ b/app/src/main/res/drawable/emoji_selected_circle.xml
@@ -0,0 +1,21 @@
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gray_border_bookmark.xml b/app/src/main/res/drawable/gray_border_bookmark.xml
new file mode 100644
index 0000000..f314b19
--- /dev/null
+++ b/app/src/main/res/drawable/gray_border_bookmark.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_friend.xml b/app/src/main/res/drawable/ic_friend.xml
new file mode 100644
index 0000000..d447995
--- /dev/null
+++ b/app/src/main/res/drawable/ic_friend.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/manage_search_24px.xml b/app/src/main/res/drawable/manage_search_24px.xml
index 6ddb58f..d64ff63 100644
--- a/app/src/main/res/drawable/manage_search_24px.xml
+++ b/app/src/main/res/drawable/manage_search_24px.xml
@@ -3,7 +3,7 @@
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
- android:tint="?attr/colorControlNormal"
+ android:tint="@color/primary_color"
android:autoMirrored="true">
+
+
diff --git a/app/src/main/res/drawable/outline_calendar_month_24.xml b/app/src/main/res/drawable/outline_calendar_month_24.xml
new file mode 100644
index 0000000..915b8b5
--- /dev/null
+++ b/app/src/main/res/drawable/outline_calendar_month_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/outline_circle_24.xml b/app/src/main/res/drawable/outline_circle_24.xml
new file mode 100644
index 0000000..d8879d2
--- /dev/null
+++ b/app/src/main/res/drawable/outline_circle_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/person_alert_24px.xml b/app/src/main/res/drawable/person_alert_24px.xml
new file mode 100644
index 0000000..a232d8f
--- /dev/null
+++ b/app/src/main/res/drawable/person_alert_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/refresh_24px.xml b/app/src/main/res/drawable/refresh_24px.xml
new file mode 100644
index 0000000..f4302a5
--- /dev/null
+++ b/app/src/main/res/drawable/refresh_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/search_filter_bottomsheet_background.xml b/app/src/main/res/drawable/search_filter_bottomsheet_background.xml
index d62de07..95668dc 100644
--- a/app/src/main/res/drawable/search_filter_bottomsheet_background.xml
+++ b/app/src/main/res/drawable/search_filter_bottomsheet_background.xml
@@ -2,8 +2,11 @@
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/search_filter_date_background.xml b/app/src/main/res/drawable/search_filter_date_background.xml
new file mode 100644
index 0000000..69fb037
--- /dev/null
+++ b/app/src/main/res/drawable/search_filter_date_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/search_filter_date_gray_background.xml b/app/src/main/res/drawable/search_filter_date_gray_background.xml
new file mode 100644
index 0000000..0833617
--- /dev/null
+++ b/app/src/main/res/drawable/search_filter_date_gray_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/share_26dp_5f6368_fill0_wght300_grad0_opsz24.xml b/app/src/main/res/drawable/share_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
new file mode 100644
index 0000000..e23dc8d
--- /dev/null
+++ b/app/src/main/res/drawable/share_26dp_5f6368_fill0_wght300_grad0_opsz24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/story_ring_not_updated.xml b/app/src/main/res/drawable/story_ring_not_updated.xml
new file mode 100644
index 0000000..ed52129
--- /dev/null
+++ b/app/src/main/res/drawable/story_ring_not_updated.xml
@@ -0,0 +1,12 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/story_ring_updated.xml b/app/src/main/res/drawable/story_ring_updated.xml
new file mode 100644
index 0000000..35b12d3
--- /dev/null
+++ b/app/src/main/res/drawable/story_ring_updated.xml
@@ -0,0 +1,12 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/tag_24px.xml b/app/src/main/res/drawable/tag_24px.xml
new file mode 100644
index 0000000..40b2457
--- /dev/null
+++ b/app/src/main/res/drawable/tag_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_kakao_login.xml b/app/src/main/res/layout/activity_kakao_login.xml
index 0f33afb..2a75d07 100644
--- a/app/src/main/res/layout/activity_kakao_login.xml
+++ b/app/src/main/res/layout/activity_kakao_login.xml
@@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
- tools:context=".presentation.view.KakaoLoginActivity">
+ tools:context=".presentation.view.main.KakaoLoginActivity">
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/category_popup.xml b/app/src/main/res/layout/category_popup.xml
index 3ab09dd..1504434 100644
--- a/app/src/main/res/layout/category_popup.xml
+++ b/app/src/main/res/layout/category_popup.xml
@@ -19,8 +19,8 @@
@@ -24,6 +24,7 @@
android:layout_marginBottom="5dp"
android:text="nickName"
android:textColor="@color/primary_color"
+ android:textSize="16sp"
android:textStyle="bold" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/custom_notification.xml b/app/src/main/res/layout/custom_notification.xml
new file mode 100644
index 0000000..554853a
--- /dev/null
+++ b/app/src/main/res/layout/custom_notification.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/emotion_window.xml b/app/src/main/res/layout/emotion_window.xml
index 6cd6d21..71c09c5 100644
--- a/app/src/main/res/layout/emotion_window.xml
+++ b/app/src/main/res/layout/emotion_window.xml
@@ -8,42 +8,46 @@
android:orientation="horizontal"
android:paddingStart="7dp"
android:paddingTop="2dp"
- android:paddingEnd="2dp"
- android:paddingBottom="2dp">
+ android:paddingBottom="5dp">
+ android:textSize="22sp" />
+ android:textSize="22sp" />
+ android:textSize="22sp" />
+ android:textSize="22sp" />
+ android:textSize="22sp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_calendar_view.xml b/app/src/main/res/layout/fragment_calendar_view.xml
index 3edcc3a..4a8f4ac 100644
--- a/app/src/main/res/layout/fragment_calendar_view.xml
+++ b/app/src/main/res/layout/fragment_calendar_view.xml
@@ -6,30 +6,58 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
- tools:context=".presentation.view.CalendarViewFragment">
+ tools:context=".presentation.view.main.CalendarViewFragment">
-
-
+
+
+
+
+
+
+
+
+
+ tools:context=".presentation.view.sub.diary.DiaryEditFragment">
@@ -123,29 +127,36 @@
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="30dp"
- android:layout_marginStart="5dp"
+ android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:background="@android:color/transparent"
+ android:hint="@string/address_hint"
+ android:lines="1"
+ android:singleLine="true"
android:text="address"
+ android:textColorHint="#838383"
android:textSize="17sp" />
@@ -175,20 +191,20 @@
@@ -196,11 +212,11 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginStart="5dp"
+ android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:background="@android:color/transparent"
android:hint="@string/diary_hint_sentence"
- android:inputType="text" />
+ android:inputType="textMultiLine" />
diff --git a/app/src/main/res/layout/fragment_diary_read.xml b/app/src/main/res/layout/fragment_diary_read.xml
index d6322a1..af5ff14 100644
--- a/app/src/main/res/layout/fragment_diary_read.xml
+++ b/app/src/main/res/layout/fragment_diary_read.xml
@@ -6,7 +6,7 @@
android:layout_height="match_parent"
android:background="#515151"
android:orientation="vertical"
- tools:context=".presentation.view.DiaryReadFragment">
+ tools:context=".presentation.view.sub.diary.DiaryReadFragment">
@@ -142,9 +142,11 @@
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:background="@drawable/category_background"
- android:padding="3dp"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
+ android:gravity="center"
+ android:paddingStart="5dp"
+ android:paddingTop="2dp"
+ android:paddingEnd="5dp"
+ android:paddingBottom="2dp"
android:textColor="@color/white"
android:visibility="visible"
tools:visibility="visible" />
@@ -155,9 +157,11 @@
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:background="@drawable/category_background"
- android:padding="3dp"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
+ android:gravity="center"
+ android:paddingStart="5dp"
+ android:paddingTop="2dp"
+ android:paddingEnd="5dp"
+ android:paddingBottom="2dp"
android:textColor="@color/white"
android:visibility="visible"
tools:visibility="visible" />
@@ -165,21 +169,22 @@
@@ -187,7 +192,7 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginStart="5dp"
+ android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:text="content"
android:textSize="17sp"
diff --git a/app/src/main/res/layout/fragment_friend_request.xml b/app/src/main/res/layout/fragment_friend_request.xml
index bb04310..ab0b492 100644
--- a/app/src/main/res/layout/fragment_friend_request.xml
+++ b/app/src/main/res/layout/fragment_friend_request.xml
@@ -75,8 +75,10 @@
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/searchUserEditText"
+ app:layout_constraintVertical_bias="1.0"
tools:listitem="@layout/friend_request_item" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_friend_request_list.xml b/app/src/main/res/layout/fragment_friend_request_list.xml
new file mode 100644
index 0000000..3ea221c
--- /dev/null
+++ b/app/src/main/res/layout/fragment_friend_request_list.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_friends_list.xml b/app/src/main/res/layout/fragment_friends_list.xml
index f323a4d..3a18def 100644
--- a/app/src/main/res/layout/fragment_friends_list.xml
+++ b/app/src/main/res/layout/fragment_friends_list.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
- tools:context=".presentation.view.FriendsListFragment">
+ tools:context=".presentation.view.sub.friends.FriendsListFragment">
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_notification.xml b/app/src/main/res/layout/fragment_notification.xml
index 11e470e..9cd1537 100644
--- a/app/src/main/res/layout/fragment_notification.xml
+++ b/app/src/main/res/layout/fragment_notification.xml
@@ -6,7 +6,7 @@
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
- tools:context=".presentation.view.NotificationFragment">
+ tools:context=".presentation.view.sub.NotificationFragment">
+ tools:context=".presentation.view.sub.PostFragment">
+ tools:context=".presentation.view.main.search.SearchFragment">
+ android:layout_marginStart="5dp"
+ android:layout_marginEnd="5dp"
+ android:layout_marginTop="5dp"
+ android:paddingBottom="5dp"
+ android:paddingEnd="5dp"
+ android:paddingStart="5dp">
-
+ android:background="@drawable/search_view_background"
+ android:drawableStart="@drawable/search_20px"
+ android:drawablePadding="8dp"
+ android:drawableTint="@color/search_icon_background"
+ android:hint="@string/search_window_guide"
+ android:inputType="text"
+ android:padding="10dp"
+ android:textSize="14sp"
+ app:layout_constraintEnd_toStartOf="@id/filter"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent" />
-
+
-
-
-
+ android:text="@string/search_filter"
+ android:textColor="@color/primary_color"
+ android:layout_gravity="bottom"/>
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_setting.xml b/app/src/main/res/layout/fragment_setting.xml
index 963c331..8400f99 100644
--- a/app/src/main/res/layout/fragment_setting.xml
+++ b/app/src/main/res/layout/fragment_setting.xml
@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
- tools:context=".presentation.view.SettingFragment">
+ tools:context=".presentation.view.main.SettingFragment">
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/pushNotification" />
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/timeInterval">
+ android:textColor="@color/white"
+ android:textSize="15sp" />
+ android:textColor="@color/white"
+ android:textSize="15sp" />
+ android:textColor="@color/white"
+ android:textSize="15sp" />
+ android:textColor="@color/white"
+ android:textSize="15sp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_share_view.xml b/app/src/main/res/layout/fragment_share_view.xml
new file mode 100644
index 0000000..9cc8ece
--- /dev/null
+++ b/app/src/main/res/layout/fragment_share_view.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_today_log.xml b/app/src/main/res/layout/fragment_today_log.xml
index bd8f2f2..3622e65 100644
--- a/app/src/main/res/layout/fragment_today_log.xml
+++ b/app/src/main/res/layout/fragment_today_log.xml
@@ -7,24 +7,35 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white"
- tools:context=".presentation.view.TodayLogFragment">
+ tools:context=".presentation.view.main.TodayLogFragment">
+ android:layout_height="wrap_content">
+
+
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/friend_request_list_item.xml b/app/src/main/res/layout/friend_request_list_item.xml
new file mode 100644
index 0000000..79ef207
--- /dev/null
+++ b/app/src/main/res/layout/friend_request_list_item.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/notification_item.xml b/app/src/main/res/layout/notification_item.xml
index 8416d96..f9a1902 100644
--- a/app/src/main/res/layout/notification_item.xml
+++ b/app/src/main/res/layout/notification_item.xml
@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="80dp">
+ android:layout_height="90dp">
@@ -125,7 +126,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
- android:layout_marginTop="50dp"
+ android:layout_marginTop="60dp"
android:text="content"
android:textSize="17sp"
android:visibility="visible"
diff --git a/app/src/main/res/layout/search_filter_bottomsheet.xml b/app/src/main/res/layout/search_filter_bottomsheet.xml
deleted file mode 100644
index 4e79a33..0000000
--- a/app/src/main/res/layout/search_filter_bottomsheet.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/share_item.xml b/app/src/main/res/layout/share_item.xml
new file mode 100644
index 0000000..8ca366d
--- /dev/null
+++ b/app/src/main/res/layout/share_item.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/timeline_item.xml b/app/src/main/res/layout/timeline_item.xml
index 3d3a64a..8534fcf 100644
--- a/app/src/main/res/layout/timeline_item.xml
+++ b/app/src/main/res/layout/timeline_item.xml
@@ -25,6 +25,7 @@
android:id="@+id/timeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
android:hint="오전 10:00"
android:textSize="10sp" />
@@ -43,25 +44,25 @@
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:src="@drawable/delete_26dp_5f6368_fill0_wght300_grad0_opsz24" />
@@ -84,8 +85,8 @@
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index d16fb62..137379a 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,7 +1,18 @@
-
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index c1f6db8..938d8af 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -10,4 +10,5 @@
#61000000
#D6D6D6
#E5E5E5
+ #B6B6B6
\ 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 e43bf28..cac26c2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,14 +11,18 @@
삭제
프로필
알림
+ 자동 기록 알림
+ 푸시 알림
시간 간격 설정
15분
20분
25분
30분
시간 간격이 %1$s으로 설정되었습니다
- 알림이 설정되었습니다
- 알림이 해제되었습니다
+ 자동 기록 알림이 설정되었습니다
+ 자동 기록 알림이 해제되었습니다
+ 푸시 알림이 설정되었습니다
+ 푸시 알림이 해제되었습니다
수락
거절
간편하게 로그인하고
@@ -53,8 +57,31 @@
검색 결과가 없습니다.
친구
신청됨
+ 장소명
+ 주소
닉네임은 한 글자 이상이어야 합니다
닉네임은 여섯 글자 이하여야 합니다
카테고리는 한 글자 이상이어야 합니다
카테고리는 여섯 글자 이하여야 합니다
+ 북마크로 검색하기
+ 감정 표현으로 검색하기
+ 날짜로 검색하기
+ 닫기
+ #카테고리
+ 카테고리로 검색하기
+ 추가된 카테고리가 없습니다
+ 초기화
+ 적용하기
+ 시작
+ 종료
+ 시작일이 종료일보다 이를 수 없습니다
+ 검색 필터
+ "FCM 채널 설명"
+ "서비스 상태"
+ "현재 XX 위치에 머무르고 있어요!\n지금의 기분은 어떠신가요?"
+ 친구수락
+ 친구요청이 아직 안 왔습니다.
+ 친구요청목록
+ 시작일을 입력해주셔야 합니다
+ 종료일을 입력해주셔야 합니다
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 2a33f7f..99c6f7d 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -15,6 +15,6 @@
- true
- 0.72
-
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 78ed83e..c5c6d2a 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -2,9 +2,17 @@
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index a0985ef..8ad463d 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
+ id("com.google.gms.google-services") version "4.4.2" apply false
}
\ No newline at end of file