├── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── buildSrc
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── Dependencies.kt
├── data
├── build.gradle.kts
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── team
│ └── dahaeng
│ └── android
│ └── data
│ ├── aouth
│ ├── mapper
│ │ └── mapper.kt
│ └── repository
│ │ └── AouthRepositoryImpl.kt
│ ├── community
│ └── repository
│ │ └── FirebaseRepositoryImpl.kt
│ └── util
│ ├── Constants.kt
│ ├── DataLayerUtil.kt
│ ├── extensions.kt
│ └── typealias.kt
├── domain
├── build.gradle.kts
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── team
│ └── dahaeng
│ └── android
│ └── domain
│ ├── aouth
│ ├── model
│ │ └── User.kt
│ ├── repository
│ │ └── AouthRepository.kt
│ └── usecase
│ │ └── KakaoLoginUseCase.kt
│ └── community
│ ├── model
│ ├── common
│ │ └── Photo.kt
│ ├── post
│ │ └── Post.kt
│ ├── schedule
│ │ └── Schedule.kt
│ └── travel
│ │ ├── Accommodation.kt
│ │ ├── Course.kt
│ │ ├── CourseList.kt
│ │ ├── Locate.kt
│ │ ├── Period.kt
│ │ ├── Place.kt
│ │ ├── Target.kt
│ │ ├── Theme.kt
│ │ ├── Transportation.kt
│ │ └── Travel.kt
│ ├── repository
│ └── FirebaseRepository.kt
│ └── usecase
│ ├── post
│ ├── ImportPostsUseCase.kt
│ ├── UploadImageUseCase.kt
│ └── UploadPostUseCase.kt
│ └── schedule
│ ├── ChangeScheduleUseCase.kt
│ ├── DeleteScheduleUseCase.kt
│ ├── ImportScheduleUseCase.kt
│ └── UploadScheduleUseCase.kt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── naming-convention.md
├── presentation
├── build.gradle.kts
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── kotlin
│ └── team
│ │ └── dahaeng
│ │ └── android
│ │ ├── DahaengAndroid.kt
│ │ ├── activity
│ │ ├── base
│ │ │ ├── BaseActivity.kt
│ │ │ ├── BaseFragment.kt
│ │ │ └── BaseViewModel.kt
│ │ ├── createschedule
│ │ │ └── CreateScheduleActivity.kt
│ │ ├── error
│ │ │ └── ErrorActivity.kt
│ │ ├── login
│ │ │ ├── LoginActivity.kt
│ │ │ └── LoginViewModel.kt
│ │ ├── main
│ │ │ ├── MainActivity.kt
│ │ │ ├── MainViewModel.kt
│ │ │ └── fragment
│ │ │ │ ├── like
│ │ │ │ └── LikeFragment.kt
│ │ │ │ ├── list
│ │ │ │ ├── ListAdapter.kt
│ │ │ │ └── ListFragment.kt
│ │ │ │ └── schedule
│ │ │ │ ├── DetailScheduleFragment.kt
│ │ │ │ ├── ScheduleAdapter.kt
│ │ │ │ └── ScheduleFragment.kt
│ │ ├── modifyschedule
│ │ │ ├── ModifyCourseActivity.kt
│ │ │ ├── ModifyCourseAdapter.kt
│ │ │ ├── ModifyScheduleActivity.kt
│ │ │ ├── ModifyScheduleAdapter.kt
│ │ │ ├── ModifyScheduleViewModel.kt
│ │ │ └── PlaceAdapter.kt
│ │ └── tasking
│ │ │ ├── TaskingActivity.kt
│ │ │ └── TaskingViewModel.kt
│ │ ├── data
│ │ └── DataStore.kt
│ │ ├── di
│ │ ├── common
│ │ │ └── SharedPreferencesModule.kt
│ │ ├── repository
│ │ │ └── RepositoryModule.kt
│ │ └── usecase
│ │ │ ├── AouthUseCaseModule.kt
│ │ │ └── CommunityUseCaseModule.kt
│ │ ├── ui
│ │ └── databinding
│ │ │ └── ImageViewAdapter.kt
│ │ └── util
│ │ ├── NetworkUtil.kt
│ │ ├── constants
│ │ └── Key.kt
│ │ ├── extensions
│ │ ├── Flow.kt
│ │ ├── LifeCycle.kt
│ │ ├── SharedPreferences.kt
│ │ ├── json.kt
│ │ └── toast.kt
│ │ └── test
│ │ └── TestUtil.kt
│ └── res
│ ├── drawable
│ ├── bg_intro_thumbnail.png
│ ├── bg_rounded_blue.xml
│ ├── bg_rounded_lightblue.xml
│ ├── ic_baseline_edit_24.xml
│ ├── ic_baseline_more_24.xml
│ ├── ic_baseline_post_add_24.xml
│ ├── ic_baseline_reorder_24.xml
│ ├── ic_outline_location_on_24.xml
│ ├── ic_round_airplane_ticket_24.xml
│ ├── ic_round_card_travel_24.xml
│ ├── ic_round_castle_24.xml
│ ├── ic_round_favorite_24.xml
│ ├── ic_round_filter_list_24.xml
│ ├── ic_round_search_24.xml
│ ├── ic_round_star_24.xml
│ └── ic_splash_logo.png
│ ├── font
│ ├── nanumbarungothic.ttf
│ └── nanumbarunpen_b.ttf
│ ├── layout
│ ├── activity_create_schedule.xml
│ ├── activity_error.xml
│ ├── activity_login.xml
│ ├── activity_main.xml
│ ├── activity_modify_course.xml
│ ├── activity_modify_schedule.xml
│ ├── activity_tasking.xml
│ ├── fragment_deatil_schedule.xml
│ ├── fragment_like.xml
│ ├── fragment_list.xml
│ ├── fragment_schedule.xml
│ ├── layout_avatar.xml
│ ├── layout_modify_course.xml
│ ├── layout_modify_schedule.xml
│ ├── layout_post.xml
│ ├── layout_rv_modfiy_schedule_item.xml
│ └── layout_schedule.xml
│ ├── menu
│ ├── main_menu.xml
│ └── schedule_menu.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── navigation
│ └── main_navigation.xml
│ ├── raw
│ ├── no_internet.json
│ └── request_fail.json
│ ├── values-v27
│ └── themes.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
├── secrets.tar.gpg
└── settings.gradle.kts
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | secrets.tar
3 | local.properties
4 | google-services.json
5 | /.idea
6 | /build
7 | /buildSrc/.gradle/
8 | /buildSrc/build/
9 | /data/build
10 | /domain/build
11 | /presentation/build
12 | /presentation/release
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Dahaeng
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 다행 [](https://www.codefactor.io/repository/github/dahaeng/dahaeng-android)
2 |
3 | > **다**같이 정하는 여**행** 계획
4 |
5 | 매번 발생하는 읽씹과 파토나는 여행 계획 세우기.
6 | 한 번에, 빠르고, 편리하게 일정을 잡을 수 있게 도와드립니다 ✨
7 |
8 | ---
9 |
10 | # 프로젝트 규칙
11 |
12 | 1. 클린 아키텍처 적용
13 | 2. [코틀린 린트](https://ktlint.github.io/)
14 | , [다행 네이밍 컨벤션](https://github.com/dahaeng/dahaeng-android/blob/develop/naming-convention.md)으로 코드
15 | 스타일 통일
16 | 3. 프로젝트 최대한 깔끔하게 진행 (warning 지양)
17 |
18 | # 개발
19 |
20 | - [@jisungbin](https://github.com/jisungbin)
21 | - [@210202](https://github.com/jkey20)
22 |
23 | # 수익 모델
24 |
25 | 주변 여행지 검색시 더 자세한 정보(평점, 영업시간, 메뉴판, 사진 등등)를 보기 위해선 계정 업그레이드 필요
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath("com.android.tools.build:gradle:${Versions.Essential.Gradle}")
9 | classpath("com.google.gms:google-services:${Versions.Essential.GoogleService}")
10 | classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.Jetpack.Hilt}")
11 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Essential.Kotlin}")
12 | classpath("com.google.android.gms:oss-licenses-plugin:${Versions.OssLicense.Classpath}")
13 | classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:${Versions.Util.SecretsGradlePlugin}")
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | maven { setUrl("https://jitpack.io") }
22 | maven { setUrl("https://devrepo.kakao.com/nexus/content/groups/public/") }
23 | }
24 | }
25 |
26 | tasks.register("clean", Delete::class) {
27 | allprojects.map { it.buildDir }.forEach(::delete)
28 | }
29 |
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
4 |
5 | repositories {
6 | gradlePluginPortal()
7 | }
8 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/Dependencies.kt:
--------------------------------------------------------------------------------
1 | import org.gradle.api.JavaVersion
2 |
3 | object Application {
4 | const val minSdk = 24
5 | const val targetSdk = 31
6 | const val compileSdk = 31
7 | const val jvmTarget = "11"
8 | const val versionCode = 1
9 | const val versionName = "1.0.0"
10 |
11 | val targetCompat = JavaVersion.VERSION_11
12 | val sourceCompat = JavaVersion.VERSION_11
13 | }
14 |
15 | object Versions {
16 | const val Kakao = "2.8.4"
17 | const val FirebaseBom = "29.0.3"
18 |
19 | object Essential {
20 | const val Kotlin = "1.6.10"
21 | const val Coroutines = "1.6.0"
22 | const val Gradle = "7.1.2"
23 | const val GoogleService = "4.3.3"
24 | }
25 |
26 | object Ktx {
27 | const val Core = "1.7.0"
28 | const val Fragment = "1.4.1"
29 | const val LifeCycle = "2.4.1"
30 | const val ViewModel = "2.4.1"
31 | const val Navigation = "2.4.1"
32 | }
33 |
34 | object Ui {
35 | const val Coil = "1.4.0"
36 | const val Lottie = "5.0.2"
37 | const val Flexbox = "3.0.0"
38 | const val Material = "1.5.0"
39 | const val AppCompat = "1.4.1"
40 | const val ExoPlayer = "2.17.0"
41 | const val Splash = "1.0.0-beta01"
42 | const val SmoothBottomBar = "1.7.9"
43 | const val ConstraintLayout = "2.1.3"
44 | }
45 |
46 | object Util {
47 | const val Moshi = "1.13.0"
48 | const val Erratum = "1.0.1"
49 | const val Logeukes = "1.0.1"
50 | const val Jackson = "2.13.1"
51 | const val LeakCanary = "2.8.1"
52 | const val SystemUiController = "1.0.0"
53 | const val SecretsGradlePlugin = "2.0.0"
54 | const val CheckDependencyUpdates = "1.5.0"
55 | }
56 |
57 | object Location {
58 | const val Gms = "19.0.1"
59 | const val Locus = "4.0.1"
60 | }
61 |
62 | object Jetpack {
63 | const val Hilt = "2.41"
64 | }
65 |
66 | object OssLicense {
67 | const val Master = "17.0.0"
68 | const val Classpath = "0.10.4"
69 | }
70 | }
71 |
72 | object Dependencies {
73 | const val Kakao = "com.kakao.sdk:v2-user:${Versions.Kakao}"
74 | const val Hilt = "com.google.dagger:hilt-android:${Versions.Jetpack.Hilt}"
75 | const val FirebaseBom = "com.google.firebase:firebase-bom:${Versions.FirebaseBom}"
76 |
77 | object Compiler {
78 | const val Hilt = "com.google.dagger:hilt-android-compiler:${Versions.Jetpack.Hilt}"
79 | }
80 |
81 | val Firebase = listOf(
82 | "com.google.firebase:firebase-storage-ktx",
83 | "com.google.firebase:firebase-firestore-ktx"
84 | )
85 |
86 | val Essential = listOf(
87 | "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Essential.Coroutines}"
88 | )
89 |
90 | val Ktx = listOf(
91 | "androidx.core:core-ktx:${Versions.Ktx.Core}",
92 | "androidx.fragment:fragment-ktx:${Versions.Ktx.Fragment}",
93 | "androidx.navigation:navigation-ui-ktx:${Versions.Ktx.Navigation}",
94 | "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.Ktx.LifeCycle}",
95 | "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.Ktx.ViewModel}",
96 | "androidx.navigation:navigation-fragment-ktx:${Versions.Ktx.Navigation}"
97 | )
98 |
99 | val Ui = listOf(
100 | "io.coil-kt:coil:${Versions.Ui.Coil}",
101 | "com.airbnb.android:lottie:${Versions.Ui.Lottie}",
102 | "androidx.appcompat:appcompat:${Versions.Ui.AppCompat}",
103 | "androidx.core:core-splashscreen:${Versions.Ui.Splash}",
104 | "com.google.android.flexbox:flexbox:${Versions.Ui.Flexbox}",
105 | "com.google.android.material:material:${Versions.Ui.Material}",
106 | "com.google.android.exoplayer:exoplayer:${Versions.Ui.ExoPlayer}",
107 | "com.google.android.exoplayer:exoplayer-core:${Versions.Ui.ExoPlayer}",
108 | "com.github.ibrahimsn98:SmoothBottomBar:${Versions.Ui.SmoothBottomBar}",
109 | "androidx.constraintlayout:constraintlayout:${Versions.Ui.ConstraintLayout}",
110 | "com.google.android.gms:play-services-oss-licenses:${Versions.OssLicense.Master}",
111 | )
112 |
113 | val Util = listOf(
114 | "com.squareup.moshi:moshi:${Versions.Util.Moshi}",
115 | "io.github.jisungbin:erratum:${Versions.Util.Erratum}",
116 | "io.github.jisungbin:logeukes:${Versions.Util.Logeukes}",
117 | "land.sungbin:systemuicontroller:${Versions.Util.SystemUiController}"
118 | )
119 |
120 | val Location = listOf(
121 | "com.github.BirjuVachhani:locus-android:${Versions.Location.Locus}",
122 | "com.google.android.gms:play-services-location:${Versions.Location.Gms}"
123 | )
124 |
125 | val Jackson = listOf(
126 | "com.fasterxml.jackson.core:jackson-core:${Versions.Util.Jackson}",
127 | "com.fasterxml.jackson.core:jackson-databind:${Versions.Util.Jackson}",
128 | "com.fasterxml.jackson.core:jackson-annotations:${Versions.Util.Jackson}",
129 | "com.fasterxml.jackson.module:jackson-module-kotlin:${Versions.Util.Jackson}"
130 | )
131 |
132 | val Debug = listOf(
133 | "com.squareup.leakcanary:leakcanary-android:${Versions.Util.LeakCanary}"
134 | )
135 | }
136 |
--------------------------------------------------------------------------------
/data/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | id("kotlin-android")
4 | id("com.google.gms.google-services")
5 | }
6 |
7 | android {
8 | compileSdk = Application.compileSdk
9 |
10 | defaultConfig {
11 | minSdk = Application.minSdk
12 | targetSdk = Application.targetSdk
13 | multiDexEnabled = true
14 | }
15 |
16 | sourceSets {
17 | getByName("main").run {
18 | java.srcDirs("src/main/kotlin")
19 | }
20 | }
21 |
22 | compileOptions {
23 | sourceCompatibility = Application.sourceCompat
24 | targetCompatibility = Application.targetCompat
25 | }
26 |
27 | kotlinOptions {
28 | jvmTarget = Application.jvmTarget
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation(projects.domain)
34 | implementation(Dependencies.Kakao)
35 | implementation(platform(Dependencies.FirebaseBom))
36 |
37 | Dependencies.Firebase.forEach(::implementation)
38 | Dependencies.Essential.forEach(::implementation)
39 | }
40 |
--------------------------------------------------------------------------------
/data/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/aouth/mapper/mapper.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [mapper.kt] created by Ji Sungbin on 22. 1. 6. 오전 1:56
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.aouth.mapper
11 |
12 | import com.kakao.sdk.user.model.User
13 | import team.dahaeng.android.data.util.UserDomain
14 | import kotlin.random.Random
15 |
16 | fun User.toDomain() = UserDomain(
17 | id = id ?: Random.nextLong(),
18 | nickname = kakaoAccount?.profile?.nickname ?: UserDomain.getDefaultNickname(),
19 | profileImageUrl = kakaoAccount?.profile?.profileImageUrl
20 | ?: UserDomain.getDefaultProfileImageColor()
21 | )
22 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/aouth/repository/AouthRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [LoginRepositoryImpl.kt] created by Ji Sungbin on 22. 1. 6. 오전 1:37
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.aouth.repository
11 |
12 | import android.content.Context
13 | import com.kakao.sdk.user.UserApiClient
14 | import com.kakao.sdk.user.model.User
15 | import kotlinx.coroutines.suspendCancellableCoroutine
16 | import team.dahaeng.android.data.aouth.mapper.toDomain
17 | import team.dahaeng.android.data.util.UserDomain
18 | import team.dahaeng.android.domain.aouth.repository.AouthRepository
19 | import kotlin.coroutines.resume
20 |
21 | private const val RESPONSE_NOTHING = "Kakao API response is nothing."
22 |
23 | class AouthRepositoryImpl : AouthRepository {
24 | override suspend fun kakaoLogin(context: Context): UserDomain {
25 | if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
26 | loginWithKakaoTalk(context)
27 | } else {
28 | loginWithWebView(context)
29 | }
30 | return getUser().toDomain()
31 | }
32 |
33 | private suspend fun loginWithKakaoTalk(context: Context): Unit =
34 | suspendCancellableCoroutine { continuation ->
35 | UserApiClient.instance.loginWithKakaoTalk(context) { token, error ->
36 | continuation.resume(
37 | when {
38 | error != null -> throw error
39 | token != null -> Unit
40 | else -> throw Throwable(RESPONSE_NOTHING)
41 | }
42 | )
43 | }
44 | }
45 |
46 | private suspend fun loginWithWebView(context: Context): Unit =
47 | suspendCancellableCoroutine { continuation ->
48 | UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
49 | continuation.resume(
50 | when {
51 | error != null -> throw error
52 | token != null -> Unit
53 | else -> throw Throwable(RESPONSE_NOTHING)
54 | }
55 | )
56 | }
57 | }
58 |
59 | private suspend fun getUser(): User = suspendCancellableCoroutine { continuation ->
60 | UserApiClient.instance.me { user, error ->
61 | continuation.resume(
62 | when {
63 | error != null -> throw error
64 | user != null -> user
65 | else -> throw Throwable(RESPONSE_NOTHING)
66 | }
67 | )
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/community/repository/FirebaseRepositoryImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [FirebaseRepositoryImpl.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.community.repository
11 |
12 | import com.google.firebase.firestore.DocumentSnapshot
13 | import com.google.firebase.firestore.ktx.firestore
14 | import com.google.firebase.ktx.Firebase
15 | import com.google.firebase.storage.ktx.storage
16 | import kotlinx.coroutines.suspendCancellableCoroutine
17 | import team.dahaeng.android.data.util.Constants
18 | import team.dahaeng.android.data.util.toObjectNonNull
19 | import team.dahaeng.android.domain.community.model.common.Photo
20 | import team.dahaeng.android.domain.community.model.post.Post
21 | import team.dahaeng.android.domain.community.model.schedule.Schedule
22 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
23 | import kotlin.coroutines.resume
24 |
25 | private const val UPLOAD_IMAGE_EXCEPTION = "이미지 업로드중 에러"
26 |
27 | class FirebaseRepositoryImpl : FirebaseRepository {
28 |
29 | private val firestore by lazy { Firebase.firestore }
30 | private val storageRef by lazy { Firebase.storage.reference }
31 |
32 | /**
33 | * @return 성공시 이미지 주소, 실패시 null
34 | */
35 | // override suspend fun uploadImage(uri: Uri, imageName: String): String? =
36 | // suspendCancellableCoroutine { continuation ->
37 | // storageRef.child(Constants.Firestore.Post).run {
38 | // child(imageName)
39 | // .putFile(uri)
40 | // .continueWithTask { task ->
41 | // if (!task.isSuccessful && task.exception != null) {
42 | // continuation.resume(null)
43 | // throw task.exception!!
44 | // }
45 | // downloadUrl
46 | // }.addOnCompleteListener { task ->
47 | // if (task.isSuccessful && task.result != null) {
48 | // continuation.resume(task.result!!.toString())
49 | // } else {
50 | // continuation.resume(null)
51 | // throw task.exception ?: Exception(UPLOAD_IMAGE_EXCEPTION)
52 | // }
53 | // }
54 | // }
55 | // }
56 |
57 | override suspend fun uploadPhotos(photos: List, imageName: String): String? {
58 | TODO("Not yet implemented")
59 | }
60 |
61 | /**
62 | * @return 성공 여부 boolean
63 | */
64 | override suspend fun uploadPost(post: Post): Boolean =
65 | suspendCancellableCoroutine { continuation ->
66 | firestore.collection(Constants.Firestore.Post)
67 | .document(post.id.toString())
68 | .set(post)
69 | .addOnSuccessListener {
70 | continuation.resume(true)
71 | }.addOnFailureListener { exception ->
72 | continuation.resume(false)
73 | throw exception
74 | }
75 | }
76 |
77 | /**
78 | * 전체 포스트 조회
79 | */
80 | override suspend fun importPosts(): List =
81 | suspendCancellableCoroutine { continuation ->
82 | firestore.collection(Constants.Firestore.Post)
83 | .get()
84 | .addOnSuccessListener { result ->
85 | continuation.resume(result.documents.map(DocumentSnapshot::toObjectNonNull))
86 | }
87 | .addOnFailureListener { exception ->
88 | continuation.resume(emptyList())
89 | throw exception
90 | }
91 | }
92 |
93 | override suspend fun deletePost(): Boolean {
94 | TODO("Not yet implemented")
95 | }
96 |
97 | /**
98 | * 내 스케줄 리스트 조회
99 | */
100 | override suspend fun importSchedules(ownerId: Long): List =
101 | suspendCancellableCoroutine { continuation ->
102 | firestore.collection(Constants.Firestore.User)
103 | //.document(ownerId.toString())
104 | .document("null")
105 | .collection(Constants.Firestore.Schedule)
106 | .get()
107 | .addOnSuccessListener { result ->
108 | continuation.resume(result.documents.map(DocumentSnapshot::toObjectNonNull))
109 | }
110 | .addOnFailureListener { exception ->
111 | continuation.resume(emptyList())
112 | throw exception
113 | }
114 | }
115 |
116 | /**
117 | * 일정 업로드
118 | * @return 성공 여부 boolean
119 | */
120 | override suspend fun uploadSchedule(schedule: Schedule): Boolean =
121 | suspendCancellableCoroutine { continuation ->
122 | firestore.collection(Constants.Firestore.User)
123 | // .document(schedule.participant.first().toString())
124 | .document(schedule.participant.firstOrNull().toString())
125 | .collection(Constants.Firestore.Schedule)
126 | .document(schedule.id.toString())
127 | .set(schedule)
128 | .addOnSuccessListener {
129 | continuation.resume(true)
130 | }
131 | .addOnFailureListener { exception ->
132 | continuation.resume(false)
133 | throw exception
134 | }
135 | }
136 |
137 | /**
138 | * 일정 삭제
139 | * @return 성공 여부 boolean
140 | */
141 | override suspend fun deleteSchedule(schedule: Schedule): Boolean =
142 | suspendCancellableCoroutine { continuation ->
143 | firestore.collection(Constants.Firestore.User)
144 | // .document(schedule.participant.first().toString())
145 | .document(schedule.participant.firstOrNull().toString())
146 | .collection(Constants.Firestore.Schedule)
147 | .document(schedule.id.toString())
148 | .delete()
149 | .addOnSuccessListener {
150 | continuation.resume(true)
151 | }
152 | .addOnFailureListener { exception ->
153 | continuation.resume(false)
154 | throw exception
155 | }
156 | }
157 |
158 | override suspend fun changeSchedule(schedule: Schedule): Boolean =
159 | suspendCancellableCoroutine { continuation ->
160 | firestore.collection(Constants.Firestore.User)
161 | .document(schedule.participant.firstOrNull().toString())
162 | .collection(Constants.Firestore.Schedule)
163 | .document(schedule.id.toString())
164 | .update(schedule.toMap())
165 | .addOnSuccessListener {
166 | continuation.resume(true)
167 | }.addOnFailureListener { exception ->
168 | continuation.resume(false)
169 | throw exception
170 | }
171 | }
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/util/Constants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Constants.kt] created by Ji Sungbin on 22. 1. 13. 오후 7:12
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.util
11 |
12 | object Constants {
13 | object Firestore {
14 | const val Post = "post"
15 | const val User = "user"
16 | const val Schedule = "schedule"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/util/DataLayerUtil.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [DataLayerUtil.kt] created by Ji Sungbin on 22. 1. 14. 오후 5:56
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.util
11 |
12 | import android.content.Context
13 | import com.kakao.sdk.common.KakaoSdk
14 |
15 | object DataLayerUtil {
16 | fun initKakaoSdk(context: Context, apiKey: String) {
17 | KakaoSdk.init(context, apiKey)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/util/extensions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [extensions.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:34
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.util
11 |
12 | import com.google.firebase.firestore.DocumentSnapshot
13 |
14 | inline fun DocumentSnapshot.toObjectNonNull(): T = toObject(T::class.java)!!
15 |
--------------------------------------------------------------------------------
/data/src/main/kotlin/team/dahaeng/android/data/util/typealias.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [typealias.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:06
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data.util
11 |
12 | typealias UserDomain = team.dahaeng.android.domain.aouth.model.User
13 |
--------------------------------------------------------------------------------
/domain/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | id("kotlin-android")
4 | }
5 |
6 | android {
7 | compileSdk = Application.compileSdk
8 |
9 | defaultConfig {
10 | minSdk = Application.minSdk
11 | targetSdk = Application.targetSdk
12 | multiDexEnabled = true
13 | }
14 |
15 | sourceSets {
16 | getByName("main").run {
17 | java.srcDirs("src/main/kotlin")
18 | }
19 | }
20 |
21 | compileOptions {
22 | sourceCompatibility = Application.sourceCompat
23 | targetCompatibility = Application.targetCompat
24 | }
25 |
26 | kotlinOptions {
27 | jvmTarget = Application.jvmTarget
28 | }
29 | }
30 |
31 | dependencies {
32 | Dependencies.Essential.forEach(::implementation)
33 | }
34 |
--------------------------------------------------------------------------------
/domain/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/aouth/model/User.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [User.kt] created by Ji Sungbin on 22. 1. 6. 오전 1:01
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.aouth.model
11 |
12 | import android.graphics.drawable.ColorDrawable
13 | import kotlin.random.Random
14 |
15 | // profileImageUrl: String or ColorDrawable
16 | data class User(val id: Long, val nickname: String, val profileImageUrl: Any) {
17 | companion object {
18 | private val randomColor get() = (Math.random() * 16777215).toInt() or (0xFF shl 24)
19 | fun getDefaultNickname() = "사용자${Random.nextInt(1000, 10000)}"
20 | fun getDefaultProfileImageColor() = ColorDrawable(randomColor)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/aouth/repository/AouthRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [LoginRepository.kt] created by Ji Sungbin on 22. 1. 6. 오전 1:29
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.aouth.repository
11 |
12 | import android.content.Context
13 | import team.dahaeng.android.domain.aouth.model.User
14 |
15 | interface AouthRepository {
16 | suspend fun kakaoLogin(context: Context): User
17 | }
18 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/aouth/usecase/KakaoLoginUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [KakaoLoginUseCase.kt] created by Ji Sungbin on 22. 1. 6. 오전 1:33
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.aouth.usecase
11 |
12 | import android.content.Context
13 | import team.dahaeng.android.domain.aouth.repository.AouthRepository
14 |
15 | class KakaoLoginUseCase(private val repository: AouthRepository, private val context: Context) {
16 | suspend operator fun invoke() = runCatching {
17 | repository.kakaoLogin(context)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/common/Photo.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Photo.kt] created by Ji Sungbin on 22. 2. 13. 오후 4:08
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.common
11 |
12 | import android.graphics.Bitmap
13 | import team.dahaeng.android.domain.community.model.travel.Place
14 |
15 | /**
16 | * [Place] 에 들어갈 이미지를 Firestore 에 올리기 위해 필요한 정보들을 담는 객체
17 | *
18 | * @property bitmap 이미지 비트맵
19 | * 갤러리에서 이미지를 가져옴: URI 변환, 카메라에서 이미지를 바로 찍음: Bitmap 변환
20 | * URI은 비트맵으로 바로 변환할 수 있지만, 카메라에서 찍은 이미지를 URI로 변환하는건
21 | * 찍은 이미지를 따로 파일에 저장하고 해당 파일의 URI을 가져와야 함
22 | * TODO: 카메라로 찍은 사진도 URI로 가져오기
23 | * TODO: 비트맵을 통채로 가지고 있는건 메모리 측면에서 매우 안 좋음
24 | * @property name Firebase Storage에 저장될 이미지 이름 ({이미지 이름}.jpg 로 저장됨)
25 | */
26 | data class Photo(val bitmap: Bitmap, val name: String)
27 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/post/Post.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Post.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.post
11 |
12 | import team.dahaeng.android.domain.community.model.travel.Travel
13 | import java.util.Date
14 | import kotlin.random.Random
15 |
16 | /**
17 | * 여행지 추천 게시글 객체
18 | *
19 | * 사진은 [travel] 에 포함되므로 따로 입력받지 않음
20 | *
21 | * @property id 포스트 UUID
22 | * @property ownerId 포스트 등록자 UUID
23 | * @property title 포스트 제목
24 | * @property content 포스트 내용, HTML 컨텐츠 텍스트 span 한정으로 지원
25 | * @property travel 포스트에 첨부된 여행 정보
26 | * @property createdAt 포스트가 업로드된 시간
27 | */
28 | data class Post(
29 | val id: Long = Random.nextLong(),
30 | val ownerId: Long = 0L,
31 | val title: String = "",
32 | val content: String = "",
33 | val travel: Travel = Travel(),
34 | val createdAt: Long = Date().time,
35 | )
36 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/schedule/Schedule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Schedule.kt] created by Ji Sungbin on 22. 2. 4. 오전 12:42
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.schedule
11 |
12 | import team.dahaeng.android.domain.community.model.travel.Travel
13 | import java.io.Serializable
14 | import kotlin.random.Random
15 |
16 | /**
17 | * 일정 객체
18 | *
19 | * @property id 일정 UUID
20 | * @property participant 일정 참여자 UUID 리스트, 첫 요소는 무조건 해당 일정의 owner 임
21 | * @property title 일정 제목
22 | * @property travel 일정동안 쓰일 여행지 객체
23 | */
24 | data class Schedule(
25 | val id: Long = Random.nextLong(),
26 | val participant: List = emptyList(),
27 | var title: String = "",
28 | var travel: Travel = Travel(),
29 | ) : Serializable {
30 | fun toMap(): Map {
31 | return mapOf(
32 | "id" to id,
33 | "participant" to participant,
34 | "title" to title,
35 | "travel" to travel
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Accommodation.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Accommodation.kt] created by Ji Sungbin on 22. 2. 13. 오후 4:20
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 숙소 객체
16 | *
17 | * @property name 숙소 이름
18 | * @property locate 숙소 위치
19 | */
20 | data class Accommodation(
21 | val name: String = "",
22 | val locate: Locate = Locate(),
23 | ) : Serializable
24 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Course.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Course.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | data class Course(
15 | val transportation: Transportation = Transportation(),
16 | val period: Period = Period(),
17 | val place: Place = Place(),
18 | val accommodation: Accommodation = Accommodation(),
19 | ) : Serializable
20 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/CourseList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [CourseList.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | data class CourseList(
15 | var courses : List = emptyList()
16 | ): Serializable
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Locate.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Locate.kt] created by Ji Sungbin on 22. 2. 13. 오후 4:44
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 위치 객체
16 | *
17 | * 위도와 경도는 지도에 정확한 마커를 찍기 위해 필요함
18 | *
19 | * @property latitude 위도
20 | * @property longitude 경도
21 | * @property address 주소 (충청남도 서산시 석림동 ~~~~)
22 | */
23 | data class Locate(
24 | val latitude: Double = Double.NaN,
25 | val longitude: Double = Double.NaN,
26 | val address: String = "",
27 | ) : Serializable
28 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Period.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TravelPeriod.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:42
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 기간 객체
16 | *
17 | * 모든 값은 Date().time 형태로 가져옴
18 | *
19 | * @property from 시작 일
20 | * @property to 종료 일
21 | */
22 | data class Period(
23 | val from: Long = 0L,
24 | val to: Long = 0L,
25 | ) : Serializable
26 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Place.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Place.kt] created by Ji Sungbin on 22. 1. 13. 오후 7:01
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import team.dahaeng.android.domain.community.model.common.Photo
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 | import java.io.Serializable
15 |
16 | /**
17 | * 장소 객체
18 | *
19 | * 어느 상황에서나 공통되는 정보들로만 구성함
20 | * 교통수단이나 기간 등은 매 상황마다 달라질 수 있는 정보임
21 | *
22 | * @property mainPrice 대표되는 금액 (식당이면 대표 메뉴 금액)
23 | * @property name 장소 이름
24 | * @property locate 장소 위치
25 | * @property photos 장소의 사진들인 [Photo] 객체들을
26 | * [FirebaseRepository.uploadPhotos] 로 업로드 하여 받은 결과 -> 이미지 다운로드 주소 배열
27 | */
28 | data class Place(
29 | val mainPrice: Int = 0,
30 | val name: String = "",
31 | val locate: Locate = Locate(),
32 | val photos: List = emptyList(),
33 | ) : Serializable
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Target.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Target.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:48
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 타켓 객체
16 | *
17 | * value class 로 하게 되면 Firestore 에서 object 변환할 때 값 주입을 못하게 됨
18 | */
19 | data class Target(val value: String = "") : Serializable {
20 | companion object {
21 | val Random get() = TargetList.All.random()
22 | }
23 | }
24 |
25 | @Suppress("FunctionName", "MemberVisibilityCanBePrivate")
26 | object TargetList {
27 | val Parent = Target("부모님")
28 | val Friend = Target("친구")
29 | val Lover = Target("애인")
30 | val All = listOf(Parent, Friend, Lover)
31 |
32 | fun Other(target: String) = Target(target)
33 | }
34 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Theme.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Theme.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:44
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 테마 객체
16 | *
17 | * value class 로 하게 되면 Firestore 에서 object 변환할 때 값 주입을 못하게 됨
18 | */
19 | data class Theme(val value: String = "") : Serializable {
20 | companion object {
21 | val Random get() = ThemeList.All.random()
22 | }
23 | }
24 |
25 | @Suppress("FunctionName", "MemberVisibilityCanBePrivate")
26 | object ThemeList {
27 | val Pension = Theme("펜션")
28 | val Camping = Theme("캠핑")
29 | val Sport = Theme("스포츠")
30 | val Healing = Theme("힐링")
31 | val All = listOf(Pension, Camping, Sport, Healing)
32 |
33 | fun Other(theme: String) = Theme(theme)
34 | }
35 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Transportation.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Transportation.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:50
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import java.io.Serializable
13 |
14 | /**
15 | * 교통수단 객체
16 | *
17 | * value class 로 하게 되면 Firestore 에서 object 변환할 때 값 주입을 못하게 됨
18 | *
19 | * @property name 교통수단 이름
20 | * @property description 교통수단에 대해 자유롭게 추가 설명 기제할 필드 (버스 번호 등등)
21 | * @property price 교통수단 금액
22 | * @property availableTime 교통수단 이용가능 시간대 (자유롭게 쓸 수 있게 하기 위해 String 으로 받음)
23 | */
24 | data class Transportation(
25 | val name: String = "",
26 | val description: String = "",
27 | val price: Int = 0,
28 | val availableTime: String = "",
29 | ) : Serializable {
30 | companion object {
31 | val Random get() = TransportationList.All.random()
32 | }
33 | }
34 |
35 | @Suppress("FunctionName", "MemberVisibilityCanBePrivate")
36 | object TransportationList : Serializable {
37 | val Car = Transportation("자동차")
38 | val Bus = Transportation("버스")
39 | val Subway = Transportation("지하철")
40 | val Plane = Transportation("비행기")
41 | val Ship = Transportation("배")
42 | val All = listOf(Car, Bus, Subway, Plane, Ship)
43 |
44 | fun Other(transportation: String) = Transportation(transportation)
45 | }
46 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/model/travel/Travel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Travel.kt] created by Ji Sungbin on 22. 1. 13. 오후 6:48
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.model.travel
11 |
12 | import team.dahaeng.android.domain.community.model.post.Post
13 | import team.dahaeng.android.domain.community.model.schedule.Schedule
14 | import java.io.Serializable
15 |
16 | /**
17 | * 여행지 객체
18 | * [Post] 와 [Schedule] 에 공통적으로 쓰임
19 | *
20 | * 사용되는 객체에 다 id 필드가 있기 때문에 따로 아이디를 받지 않음
21 | *
22 | * 일정에도 1일차, 2일차,...,N일차와 같이 단계가 있으므로
23 | * 단계에 대응하기 위해 [transportations] ~ [accommodations] 는 모두 리스트이며,
24 | * N일차에 여러가지 장소에 갈 수 있으므로 element 를 list 로 받음
25 | * N일차마다 정보를 조회할 때 해당 정보 list 의 N-1 번째 index로 접근하여 가져옴
26 | *
27 | * 여행지 객체를 사용하는 필드에서 아이디로 갖고 있게 되면
28 | * source 여행지가 업데이트 됐을 경우 내가 가져와
29 | * 수정한 여행지에도 source 에서 바뀐게 반영되기 때문에
30 | * 여행지 객체를 통체로 받음
31 | * (내가 바꾼 여행 정보를 source 에 영향을
32 | * 미치지 않게 반영하는 법도 고려해야 하는 문제가 생김)
33 | *
34 | * 여행지 추가 시나리오
35 | * 1. 여행 장소인 [Place] 입력 받음
36 | * 2. 나머지 추가 정보(교통수단, 기간 등등)들 입력 받음
37 | *
38 | * @property theme 여행지 테마
39 | * @property target 여행지 추천 타켓
40 | * @property commonAddress 여행지의 공통되는 주소 (충청남도 서산시)
41 | * @property totalPrice 여행지 장소들 ([places]) 의 총 금액 (여행지 등록할 때 시스템에서 계산)
42 | * @property totalPeriod 여행지 장소들 ([places]) 의 총 기간 (여행지 등록할 때 시스템에서 계산)
43 | * @property transportations 여행지 장소들 ([places]) 의 교통편 리스트
44 | * @property periods 여행지 장소들 ([places]) 의 기간 리스트
45 | * @property places 여행지 장소 리스트
46 | * @property accommodations 여행지 장소들 ([places]) 마다 머물 숙소들
47 | *
48 | *
49 | * 2022-03-01 변경점
50 | * val courseLists -> var courseLists, courseList 하위 val -> var
51 | * 변경점은 데이터 update시에 변경점이있는 부분만 변경하는것이 좋을것 같아서 var로 변경.
52 | *
53 | */
54 | data class Travel(
55 | val theme: Theme = Theme(),
56 | val target: Target = Target(),
57 | val commonAddress: String = "",
58 | val totalPrice: Int = 0,
59 | val totalPeriod: Period = Period(),
60 | var courseLists: List = emptyList(),
61 | ) : Serializable
62 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/repository/FirebaseRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [FirebaseRepository.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.repository
11 |
12 | import team.dahaeng.android.domain.community.model.common.Photo
13 | import team.dahaeng.android.domain.community.model.post.Post
14 | import team.dahaeng.android.domain.community.model.schedule.Schedule
15 |
16 | interface FirebaseRepository {
17 | /**
18 | * 포스트 업로드에 쓰일 이미지들 업로드
19 | */
20 | suspend fun uploadPhotos(photos: List, imageName: String): String?
21 | suspend fun uploadPost(post: Post): Boolean
22 | suspend fun importPosts(): List
23 | suspend fun deletePost(): Boolean
24 | suspend fun importSchedules(ownerId: Long): List
25 | suspend fun uploadSchedule(schedule: Schedule): Boolean
26 | suspend fun deleteSchedule(schedule: Schedule): Boolean
27 | suspend fun changeSchedule(schedule: Schedule): Boolean
28 | }
29 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/post/ImportPostsUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ImportFirebaseStorageUseCase.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.post
11 |
12 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
13 |
14 | class ImportPostsUseCase(private val repository: FirebaseRepository) {
15 | suspend operator fun invoke() = runCatching {
16 | repository.importPosts()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/post/UploadImageUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [UploadFirebaseStorageUseCase.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.post
11 |
12 | import android.net.Uri
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 |
15 | class UploadImageUseCase(private val repository: FirebaseRepository) {
16 | suspend operator fun invoke(uri: Uri, imageName: String) = runCatching {
17 | //repository.uploadImage(uri, imageName)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/post/UploadPostUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [UploadPostToStorageUseCase.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.post
11 |
12 | import team.dahaeng.android.domain.community.model.post.Post
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 |
15 | class UploadPostUseCase(private val repository: FirebaseRepository) {
16 | suspend operator fun invoke(post: Post) = runCatching {
17 | repository.uploadPost(post)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/schedule/ChangeScheduleUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ChangeScheduleUseCase.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.schedule
11 |
12 | import team.dahaeng.android.domain.community.model.schedule.Schedule
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 |
15 | class ChangeScheduleUseCase(private val repository: FirebaseRepository) {
16 | suspend operator fun invoke(schedule: Schedule) = runCatching {
17 | repository.changeSchedule(schedule)
18 | }
19 | }
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/schedule/DeleteScheduleUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [DeleteScheduleUseCase.kt] created by Ji Sungbin on 22. 2. 7. 오후 5:26
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.schedule
11 |
12 | import team.dahaeng.android.domain.community.model.schedule.Schedule
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 |
15 | class DeleteScheduleUseCase(private val repository: FirebaseRepository) {
16 | suspend operator fun invoke(schedule: Schedule) = runCatching {
17 | repository.deleteSchedule(schedule)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/schedule/ImportScheduleUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ImportScheduleUseCase.kt] created by Ji Sungbin on 22. 2. 7. 오후 5:25
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.schedule
11 |
12 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
13 |
14 | class ImportScheduleUseCase(private val repository: FirebaseRepository) {
15 | suspend operator fun invoke(ownerId: Long) = runCatching {
16 | repository.importSchedules(ownerId)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/domain/src/main/kotlin/team/dahaeng/android/domain/community/usecase/schedule/UploadScheduleUseCase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [UploadScheduleUseCase.kt] created by Ji Sungbin on 22. 2. 7. 오후 5:25
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.domain.community.usecase.schedule
11 |
12 | import team.dahaeng.android.domain.community.model.schedule.Schedule
13 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
14 |
15 | class UploadScheduleUseCase(private val repository: FirebaseRepository) {
16 | suspend operator fun invoke(schedule: Schedule) = runCatching {
17 | repository.uploadSchedule(schedule)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx2048m
2 | org.gradle.configureondemand=true
3 | org.gradle.parallel=true
4 | org.gradle.caching=true
5 | android.useAndroidX=true
6 | android.enableJetifier=true
7 | android.enableResourceOptimizations=true
8 | kotlin.code.style=official
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
3 | distributionPath=wrapper/dists
4 | zipStorePath=wrapper/dists
5 | zipStoreBase=GRADLE_USER_HOME
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/naming-convention.md:
--------------------------------------------------------------------------------
1 | # 다행 네이밍 컨벤션
2 |
3 | ---
4 |
5 | # 리소스
6 |
7 | > 스네이크 표기법 사용
8 |
9 | ## strings.xml
10 |
11 | **> 타입_사용구역_주제_설명**
12 |
13 | > activity_setting_notification_access_permission (주제: notification)
14 | >
15 | > fragment_setting_toast_storage_permission_granted (주제: toast)
16 |
17 | #### 사용구역
18 |
19 | 1. dialog: 다이얼로그 리소스
20 | 2. activity: 엑티비티 리소스
21 | 3. fragment: 프레그맨트 리소스
22 | 4. bottomsheet: 바텀시트 리소스
23 |
24 | ## drawable
25 |
26 | **> 사용용도_타입_설명_사이즈**
27 |
28 | > bg_baseline_gradient_500
29 |
30 | #### 사용용도
31 |
32 | 1. bg: 배경사진 용도
33 | 2. ic: 아이콘 용도
34 |
35 | #### 타입
36 |
37 | 1. rounded: 원형
38 | 2. baseline: 기본값
39 |
40 | #### 사이즈
41 |
42 | 사이즈는 dp기준으로 하며 끝에 dp 표기는 생략함
43 |
44 | ## colors.xml
45 |
46 | **> 색이름_강도(선택사항)**
47 |
48 | > red
49 | >
50 | > blue_200
51 | >
52 | > blue_400
53 | >
54 | > blue_600
55 |
56 | ## themes.xml, View ID (XML)
57 |
58 | **> 타입_설명 (타입은 약어 사용)**
59 |
60 | > tv_header
61 | >
62 | > tv_title
63 | >
64 | > btn_register
65 |
66 | # 클래스명(파일명)
67 |
68 | > 파스칼 표기법 사용
69 |
70 | **> 이름_사용목적**
71 |
72 | > MainActivity
73 | >
74 | > SettingFragment
75 | >
76 | > LoginBottomSheet
77 |
78 | #### 사용목적
79 |
80 | 1. dialog: 다이얼로그
81 | 2. activity: 엑티비티
82 | 3. fragment: 프레그맨트
83 | 4. bottomsheet: 바텀시트
84 |
85 | #### 만약 `extension` 클래스일 경우
86 |
87 | **> 해당 `extension`의 `this` 대상으로 파일명을 작성**
88 |
89 | > TextView.kt
90 | >
91 | > Int.kt
92 | >
93 | > String.kt
94 |
95 | #### 만약 해당 `extension`의 `this` 대상이 `Unit`일 경우
96 |
97 | **> 해당 `extension` 함수들의 공통 목적으로 파일명을 전체 대문자로 작성**
98 |
99 | > UI.kt
100 |
--------------------------------------------------------------------------------
/presentation/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("kotlin-android")
4 | id("kotlin-kapt")
5 | id("dagger.hilt.android.plugin")
6 | id("com.google.android.gms.oss-licenses-plugin")
7 | id("name.remal.check-dependency-updates") version Versions.Util.CheckDependencyUpdates
8 | id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
9 | }
10 |
11 | android {
12 | compileSdk = Application.compileSdk
13 |
14 | defaultConfig {
15 | minSdk = Application.minSdk
16 | targetSdk = Application.targetSdk
17 | versionCode = Application.versionCode
18 | versionName = Application.versionName
19 | multiDexEnabled = true
20 | }
21 |
22 | buildFeatures {
23 | dataBinding = true
24 | }
25 |
26 | buildTypes {
27 | release {
28 | isDebuggable = false
29 | isMinifyEnabled = true
30 | isShrinkResources = true
31 | }
32 | }
33 |
34 | sourceSets {
35 | getByName("main").run {
36 | java.srcDirs("src/main/kotlin")
37 | }
38 | }
39 |
40 | compileOptions {
41 | sourceCompatibility = Application.sourceCompat
42 | targetCompatibility = Application.targetCompat
43 | }
44 |
45 | kotlinOptions {
46 | jvmTarget = Application.jvmTarget
47 | }
48 | }
49 |
50 | dependencies {
51 | val kapts = listOf(Dependencies.Compiler.Hilt)
52 |
53 | implementation(projects.data)
54 | implementation(projects.domain)
55 | implementation(Dependencies.Hilt)
56 |
57 | Dependencies.Ui.forEach(::implementation)
58 | Dependencies.Ktx.forEach(::implementation)
59 | Dependencies.Util.forEach(::implementation)
60 | Dependencies.Jackson.forEach(::implementation)
61 | Dependencies.Location.forEach(::implementation)
62 | Dependencies.Essential.forEach(::implementation)
63 |
64 | Dependencies.Debug.forEach(::debugImplementation)
65 |
66 | kapts.forEach(::kapt)
67 | }
68 |
--------------------------------------------------------------------------------
/presentation/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
21 |
25 |
29 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
46 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/DahaengAndroid.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [DahaengAndroid.kt] created by Ji Sungbin on 22. 1. 5. 오후 4:51
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android
11 |
12 | import android.app.Application
13 | import android.content.Intent
14 | import dagger.hilt.android.HiltAndroidApp
15 | import io.github.jisungbin.erratum.Erratum
16 | import io.github.jisungbin.erratum.ErratumExceptionActivity
17 | import io.github.jisungbin.logeukes.Logeukes
18 | import team.dahaeng.android.activity.error.ErrorActivity
19 | import team.dahaeng.android.data.util.DataLayerUtil
20 | import team.dahaeng.android.util.constants.Key
21 |
22 | @HiltAndroidApp
23 | class DahaengAndroid : Application() {
24 | override fun onCreate() {
25 | super.onCreate()
26 |
27 | Erratum.setup(
28 | application = this,
29 | registerExceptionActivityIntent = { _, throwable, lastActivity ->
30 | Intent(lastActivity, ErrorActivity::class.java).apply {
31 | putExtra(ErratumExceptionActivity.EXTRA_EXCEPTION_STRING, throwable.toString())
32 | putExtra(
33 | ErratumExceptionActivity.EXTRA_LAST_ACTIVITY_INTENT,
34 | lastActivity.intent
35 | )
36 | putExtra(Key.Intent.Error, Key.Intent.Exception)
37 | }
38 | }
39 | )
40 | DataLayerUtil.initKakaoSdk(this, BuildConfig.KAKAO_API_KEY)
41 | if (BuildConfig.DEBUG) {
42 | Logeukes.setup()
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [BaseActivity.kt] created by Ji Sungbin on 22. 1. 5. 오후 4:48
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.base
11 |
12 | import android.os.Bundle
13 | import androidx.annotation.LayoutRes
14 | import androidx.appcompat.app.AppCompatActivity
15 | import androidx.databinding.DataBindingUtil
16 | import androidx.databinding.ViewDataBinding
17 | import androidx.databinding.library.baseAdapters.BR
18 | import androidx.lifecycle.ViewModel
19 |
20 | @Suppress("MemberVisibilityCanBePrivate")
21 | abstract class BaseActivity(@LayoutRes private val layoutId: Int) :
22 | AppCompatActivity() {
23 |
24 | abstract val vm: VM
25 | protected lateinit var binding: B
26 |
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | binding = DataBindingUtil.setContentView(this, layoutId)
30 | with(binding) {
31 | lifecycleOwner = this@BaseActivity
32 | setVariable(BR.vm, vm)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [BaseFragment.kt] created by Ji Sungbin on 22. 1. 5. 오후 4:49
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.base
11 |
12 | import android.os.Bundle
13 | import android.view.LayoutInflater
14 | import android.view.View
15 | import android.view.ViewGroup
16 | import androidx.annotation.LayoutRes
17 | import androidx.databinding.DataBindingUtil
18 | import androidx.databinding.ViewDataBinding
19 | import androidx.databinding.library.baseAdapters.BR
20 | import androidx.fragment.app.Fragment
21 | import androidx.lifecycle.ViewModel
22 |
23 | @Suppress("MemberVisibilityCanBePrivate")
24 | abstract class BaseFragment(@LayoutRes private val layoutId: Int) :
25 | Fragment() {
26 |
27 | abstract val vm: VM
28 | protected lateinit var binding: B
29 |
30 | override fun onCreateView(
31 | inflater: LayoutInflater,
32 | container: ViewGroup?,
33 | savedInstanceState: Bundle?
34 | ): View {
35 | binding = DataBindingUtil.inflate(inflater, layoutId, container, false)
36 | with(binding) {
37 | lifecycleOwner = this@BaseFragment.viewLifecycleOwner
38 | setVariable(BR.vm, vm)
39 | }
40 | return binding.root
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/base/BaseViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [BaseViewModel.kt] created by Ji Sungbin
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.base
11 |
12 | import androidx.lifecycle.ViewModel
13 | import androidx.lifecycle.viewModelScope
14 | import kotlinx.coroutines.flow.MutableSharedFlow
15 | import kotlinx.coroutines.flow.asSharedFlow
16 | import kotlinx.coroutines.launch
17 |
18 | abstract class BaseViewModel : ViewModel() {
19 | private val _exceptionFlow = MutableSharedFlow()
20 | val exceptionFlow = _exceptionFlow.asSharedFlow()
21 |
22 | open fun emitException(throwable: Throwable) = viewModelScope.launch {
23 | _exceptionFlow.emit(throwable)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/createschedule/CreateScheduleActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [CreateScheduleActivity.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.createschedule
11 |
12 | import android.os.Bundle
13 | import androidx.activity.viewModels
14 | import dagger.hilt.android.AndroidEntryPoint
15 | import team.dahaeng.android.R
16 | import team.dahaeng.android.activity.base.BaseActivity
17 | import team.dahaeng.android.activity.main.MainViewModel
18 | import team.dahaeng.android.databinding.ActivityCreateScheduleBinding
19 | import team.dahaeng.android.domain.community.model.schedule.Schedule
20 | import team.dahaeng.android.domain.community.model.travel.*
21 |
22 | @AndroidEntryPoint
23 | class CreateScheduleActivity : BaseActivity(
24 | R.layout.activity_create_schedule
25 | ) {
26 | override val vm: MainViewModel by viewModels()
27 |
28 | override fun onCreate(savedInstanceState: Bundle?) {
29 | super.onCreate(savedInstanceState)
30 |
31 | binding.btnCreateScheduleComplete.setOnClickListener {
32 | vm.addSchedule(
33 | testSchedule()
34 | )
35 |
36 | finish()
37 | }
38 | }
39 |
40 | private fun testSchedule(): Schedule {
41 | return Schedule(
42 | title = binding.textInputEditText.text.toString(),
43 | travel = Travel(
44 | theme = Theme(),
45 | commonAddress = "공통 주소",
46 | totalPrice = 1000000,
47 | totalPeriod = Period(
48 | to = 20220221,
49 | from = 20220225
50 | ),
51 | courseLists = listOf(
52 | CourseList(
53 | courses = listOf(
54 | Course(
55 | transportation = Transportation(
56 | name = "항공"
57 | ),
58 | period = Period(
59 | to = 20220221,
60 | from = 20220222
61 | ),
62 | place = Place(
63 | mainPrice = 10000,
64 | name = "장소 이름",
65 | locate = Locate(),
66 | photos = listOf("사진들")
67 | ),
68 | accommodation = Accommodation(
69 | name = "호텔",
70 | locate = Locate(),
71 | ),
72 | ),
73 |
74 | Course(
75 | transportation = Transportation(
76 | name = "배"
77 | ),
78 | period = Period(
79 | to = 20220222,
80 | from = 20220223
81 | ),
82 | place = Place(
83 | mainPrice = 20000,
84 | name = "장소 이름",
85 | locate = Locate(),
86 | photos = listOf("사진들")
87 | ),
88 | accommodation = Accommodation(
89 | name = "펜션",
90 | locate = Locate(),
91 | ),
92 | ),
93 | )
94 | ),
95 | CourseList(
96 | courses = listOf(
97 | Course(
98 | transportation = Transportation(
99 | name = "항공"
100 | ),
101 | period = Period(
102 | to = 20220223,
103 | from = 20220224
104 | ),
105 | place = Place(
106 | mainPrice = 30000,
107 | name = "장소 이름",
108 | locate = Locate(),
109 | photos = listOf("사진들")
110 | ),
111 | accommodation = Accommodation(
112 | name = "호텔",
113 | locate = Locate(),
114 | ),
115 | ),
116 |
117 | Course(
118 | transportation = Transportation(
119 | name = "배"
120 | ),
121 | period = Period(
122 | to = 20220224,
123 | from = 20220225
124 | ),
125 | place = Place(
126 | mainPrice = 40000,
127 | name = "장소 이름",
128 | locate = Locate(),
129 | photos = listOf("사진들")
130 | ),
131 | accommodation = Accommodation(
132 | name = "펜션",
133 | locate = Locate(),
134 | ),
135 | ),
136 | )
137 | )
138 | )
139 | )
140 | )
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/error/ErrorActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ErrorActivity.kt] created by Ji Sungbin on 22. 1. 19. 오후 12:05
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.error
11 |
12 | import android.os.Bundle
13 | import androidx.databinding.DataBindingUtil
14 | import io.github.jisungbin.erratum.ErratumExceptionActivity
15 | import io.github.jisungbin.logeukes.LoggerType
16 | import io.github.jisungbin.logeukes.logeukes
17 | import team.dahaeng.android.BuildConfig
18 | import team.dahaeng.android.R
19 | import team.dahaeng.android.databinding.ActivityErrorBinding
20 | import team.dahaeng.android.util.constants.Key
21 |
22 | class ErrorActivity : ErratumExceptionActivity() {
23 |
24 | private lateinit var binding: ActivityErrorBinding
25 |
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | binding = DataBindingUtil.setContentView(this, R.layout.activity_error)
29 | binding.lifecycleOwner = this
30 |
31 | when (intent.getStringExtra(Key.Intent.Error)) {
32 | Key.Intent.NoInternet -> {
33 | binding.lavLottie.run {
34 | setAnimation(R.raw.no_internet)
35 | repeatCount = 100
36 | }
37 | binding.tvException.text = getString(R.string.activity_error_no_internet)
38 | }
39 | else -> { // Key.Intent.Exception
40 | binding.lavLottie.run {
41 | setAnimation(R.raw.request_fail)
42 | setOnClickListener {
43 | playAnimation()
44 | }
45 | }
46 | binding.tvException.text = if (BuildConfig.DEBUG) {
47 | logeukes(type = LoggerType.E) { exceptionString }
48 | exceptionString
49 | } else {
50 | getString(R.string.activity_error_exception)
51 | }
52 | }
53 | }
54 |
55 | binding.btnRestart.setOnClickListener {
56 | openLastActivity()
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/login/LoginActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [LoginActivity.kt] created by Ji Sungbin on 22. 1. 5. 오후 5:13
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.login
11 |
12 | import android.content.Intent
13 | import android.content.SharedPreferences
14 | import android.os.Build
15 | import android.os.Bundle
16 | import android.view.View
17 | import android.view.ViewTreeObserver
18 | import android.view.WindowManager
19 | import android.view.animation.AnticipateInterpolator
20 | import androidx.activity.viewModels
21 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
22 | import com.google.android.exoplayer2.ExoPlayer
23 | import com.google.android.exoplayer2.MediaItem
24 | import com.google.android.exoplayer2.Player
25 | import dagger.hilt.android.AndroidEntryPoint
26 | import io.github.jisungbin.logeukes.LoggerType
27 | import io.github.jisungbin.logeukes.logeukes
28 | import team.dahaeng.android.BuildConfig
29 | import team.dahaeng.android.R
30 | import team.dahaeng.android.activity.base.BaseActivity
31 | import team.dahaeng.android.activity.error.ErrorActivity
32 | import team.dahaeng.android.activity.main.MainActivity
33 | import team.dahaeng.android.data.DataStore
34 | import team.dahaeng.android.databinding.ActivityLoginBinding
35 | import team.dahaeng.android.domain.aouth.model.User
36 | import team.dahaeng.android.util.NetworkUtil
37 | import team.dahaeng.android.util.constants.Key
38 | import team.dahaeng.android.util.extensions.collectWithLifecycle
39 | import team.dahaeng.android.util.extensions.get
40 | import team.dahaeng.android.util.extensions.launchedWhenCreated
41 | import team.dahaeng.android.util.extensions.set
42 | import team.dahaeng.android.util.extensions.toJsonString
43 | import team.dahaeng.android.util.extensions.toModel
44 | import team.dahaeng.android.util.extensions.toast
45 | import javax.inject.Inject
46 |
47 | @AndroidEntryPoint
48 | class LoginActivity : BaseActivity(R.layout.activity_login) {
49 |
50 | override val vm: LoginViewModel by viewModels()
51 | private var player: ExoPlayer? = null
52 | private var isReady = false
53 |
54 | @Inject
55 | lateinit var sharedPreferences: SharedPreferences
56 |
57 | override fun onCreate(savedInstanceState: Bundle?) {
58 | installSplashScreen()
59 | super.onCreate(savedInstanceState)
60 |
61 | if (!NetworkUtil.isNetworkAvailable(applicationContext)) {
62 | finish()
63 | startActivity(
64 | Intent(this, ErrorActivity::class.java).apply {
65 | putExtra(Key.Intent.Error, Key.Intent.NoInternet)
66 | }
67 | )
68 | return
69 | }
70 |
71 | window.setFlags(
72 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
73 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
74 | )
75 |
76 | launchedWhenCreated {
77 | vm.importPostsWithDoneAction()?.let { posts ->
78 | DataStore.updatePosts(posts)
79 | if (sharedPreferences[Key.User.KakaoProfile] != null) {
80 | // 자동 로그인 상태
81 | val me: User = sharedPreferences[Key.User.KakaoProfile]!!.toModel()
82 | DataStore.me = me
83 | startMainActivity()
84 | } else {
85 | isReady = true
86 | }
87 | }
88 | }
89 |
90 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
91 | splashScreen.setOnExitAnimationListener { splashScreenView ->
92 | splashScreenView.animate().run {
93 | alpha(0f)
94 | scaleX(0f)
95 | scaleY(0f)
96 | interpolator = AnticipateInterpolator()
97 | duration = 200L
98 | withEndAction { splashScreenView.remove() }
99 | withLayer()
100 | start()
101 | }
102 | }
103 | }
104 |
105 | binding.root.viewTreeObserver.addOnPreDrawListener(
106 | object : ViewTreeObserver.OnPreDrawListener {
107 | override fun onPreDraw(): Boolean {
108 | return if (isReady) {
109 | binding.root.viewTreeObserver.removeOnPreDrawListener(this)
110 | true
111 | } else {
112 | false
113 | }
114 | }
115 | }
116 | )
117 |
118 | binding.btnLogin.setOnClickListener {
119 | launchedWhenCreated {
120 | vm.login()?.let { user ->
121 | DataStore.me = user
122 | toast(getString(R.string.activity_login_toast_welcome))
123 | startMainActivity()
124 | sharedPreferences[Key.User.KakaoProfile] = user.toJsonString()
125 | }
126 | }
127 | }
128 |
129 | vm.exceptionFlow.collectWithLifecycle(this) { exception ->
130 | logeukes(type = LoggerType.E) { exception }
131 | toast(getString(R.string.activity_login_toast_start_fail))
132 | }
133 | }
134 |
135 | // TODO: 플리커가 왜 생기지??
136 | private fun playbackStateListener() = object : Player.Listener {
137 | override fun onPlaybackStateChanged(playbackState: Int) {
138 | when (playbackState) {
139 | ExoPlayer.STATE_BUFFERING, ExoPlayer.STATE_IDLE -> {
140 | binding.exoPlayer.visibility = View.GONE
141 | binding.ivIntroThumbnail.visibility = View.VISIBLE
142 | }
143 | ExoPlayer.STATE_READY -> {
144 | binding.exoPlayer.visibility = View.VISIBLE
145 | binding.ivIntroThumbnail.visibility = View.GONE
146 | }
147 | ExoPlayer.STATE_ENDED -> {}
148 | }
149 | }
150 | }
151 |
152 | private fun initExoPlayer() {
153 | player = ExoPlayer.Builder(this)
154 | .build()
155 | .apply {
156 | repeatMode = Player.REPEAT_MODE_ONE
157 | }
158 | .also { player ->
159 | val video = MediaItem.fromUri(BuildConfig.LOGIN_INTRO_VIDEO_URI)
160 | player.setMediaItem(video)
161 | binding.exoPlayer.player = player
162 | }
163 |
164 | player!!.addListener(playbackStateListener())
165 | player!!.playWhenReady = true
166 | player!!.prepare()
167 | }
168 |
169 | private fun releaseExoPlayer() {
170 | player?.release()
171 | player = null
172 | }
173 |
174 | override fun onStart() {
175 | super.onStart()
176 | initExoPlayer()
177 | }
178 |
179 | override fun onStop() {
180 | super.onStop()
181 | releaseExoPlayer()
182 | }
183 |
184 | private fun startMainActivity() {
185 | finish()
186 | startActivity(Intent(this, MainActivity::class.java))
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/login/LoginViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [LoginViewModel.kt] created by Ji Sungbin on 22. 1. 5. 오후 4:26
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.login
11 |
12 | import dagger.hilt.android.lifecycle.HiltViewModel
13 | import team.dahaeng.android.activity.base.BaseViewModel
14 | import team.dahaeng.android.domain.aouth.usecase.KakaoLoginUseCase
15 | import team.dahaeng.android.domain.community.usecase.post.ImportPostsUseCase
16 | import javax.inject.Inject
17 |
18 | @HiltViewModel
19 | class LoginViewModel @Inject constructor(
20 | private val kakaoLoginUseCase: KakaoLoginUseCase,
21 | private val importPostsUseCase: ImportPostsUseCase,
22 | ) : BaseViewModel() {
23 | suspend fun login() = kakaoLoginUseCase().getOrElse { exception ->
24 | emitException(exception)
25 | null
26 | }
27 |
28 | suspend fun importPostsWithDoneAction() = importPostsUseCase().getOrElse { exception ->
29 | emitException(exception)
30 | null
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [MainActivity.kt] created by Ji Sungbin on 22. 1. 17. 오전 9:55
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main
11 |
12 | import android.os.Bundle
13 | import android.widget.PopupMenu
14 | import androidx.activity.viewModels
15 | import androidx.navigation.NavController
16 | import androidx.navigation.fragment.NavHostFragment
17 | import dagger.hilt.android.AndroidEntryPoint
18 | import team.dahaeng.android.R
19 | import team.dahaeng.android.activity.base.BaseActivity
20 | import team.dahaeng.android.data.DataStore
21 | import team.dahaeng.android.databinding.ActivityMainBinding
22 |
23 | @AndroidEntryPoint
24 | class MainActivity : BaseActivity(R.layout.activity_main) {
25 |
26 | override val vm: MainViewModel by viewModels()
27 | private lateinit var navController: NavController
28 |
29 | override fun onCreate(savedInstanceState: Bundle?) {
30 | super.onCreate(savedInstanceState)
31 |
32 | vm.importSchedule(DataStore.me.id)
33 |
34 | navController =
35 | (supportFragmentManager.findFragmentById(R.id.fcv_fragment) as NavHostFragment).navController
36 | setupSmoothBottomMenu()
37 | }
38 |
39 | private fun setupSmoothBottomMenu() {
40 | val popupMenu = PopupMenu(this, null)
41 | popupMenu.inflate(R.menu.main_menu)
42 | val menu = popupMenu.menu
43 | binding.sbbMenu.setupWithNavController(menu, navController)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/MainViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [MainViewModel.kt] created by Ji Sungbin on 22. 1. 5. 오후 4:12
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main
11 |
12 | import androidx.lifecycle.viewModelScope
13 | import dagger.hilt.android.lifecycle.HiltViewModel
14 | import io.github.jisungbin.logeukes.LoggerType
15 | import io.github.jisungbin.logeukes.logeukes
16 | import kotlinx.coroutines.flow.MutableStateFlow
17 | import kotlinx.coroutines.flow.asStateFlow
18 | import kotlinx.coroutines.flow.update
19 | import kotlinx.coroutines.launch
20 | import team.dahaeng.android.activity.base.BaseViewModel
21 | import team.dahaeng.android.data.DataStore
22 | import team.dahaeng.android.domain.community.model.schedule.Schedule
23 | import team.dahaeng.android.domain.community.usecase.post.ImportPostsUseCase
24 | import team.dahaeng.android.domain.community.usecase.schedule.ChangeScheduleUseCase
25 | import team.dahaeng.android.domain.community.usecase.schedule.DeleteScheduleUseCase
26 | import team.dahaeng.android.domain.community.usecase.schedule.ImportScheduleUseCase
27 | import team.dahaeng.android.domain.community.usecase.schedule.UploadScheduleUseCase
28 | import javax.inject.Inject
29 |
30 | @HiltViewModel
31 | class MainViewModel @Inject constructor(
32 | private val importPostsUseCase: ImportPostsUseCase,
33 | private val importScheduleUseCase: ImportScheduleUseCase,
34 | private val uploadScheduleUseCase: UploadScheduleUseCase,
35 | private val deleteScheduleUseCase: DeleteScheduleUseCase,
36 | private val changeScheduleUseCase: ChangeScheduleUseCase,
37 | ) : BaseViewModel() {
38 |
39 | private val _posts = MutableStateFlow(DataStore.posts)
40 | val posts = _posts.asStateFlow()
41 |
42 | private val _schedules = MutableStateFlow(DataStore.schedules)
43 | val schedules = _schedules.asStateFlow()
44 |
45 | var lastLocate = ""
46 |
47 | fun reimportPosts() = viewModelScope.launch {
48 | importPostsUseCase()
49 | .onSuccess { posts ->
50 | if (posts.isNotEmpty()) {
51 | DataStore.updatePosts(posts)
52 | _posts.emit(posts)
53 | }
54 | }
55 | .onFailure { exception ->
56 | logeukes(type = LoggerType.E) { exception }
57 | emitException(exception)
58 | }
59 | }
60 |
61 | fun importSchedule(ownerId: Long) = viewModelScope.launch {
62 | importScheduleUseCase(ownerId)
63 | .onSuccess { scheduleList ->
64 | if (scheduleList.isNotEmpty()) {
65 | DataStore.updateSchedules(scheduleList)
66 | _schedules.emit(scheduleList)
67 | }
68 | }
69 | .onFailure { exception ->
70 | logeukes(type = LoggerType.E) { exception }
71 | emitException(exception)
72 | }
73 | }
74 |
75 | fun addSchedule(schedule: Schedule) = viewModelScope.launch {
76 | uploadScheduleUseCase(schedule)
77 | .onSuccess { isSuccess ->
78 | if (isSuccess) {
79 | _schedules.update { it + schedule }
80 | }
81 | }
82 | .onFailure { exception ->
83 | logeukes(type = LoggerType.E) { exception }
84 | emitException(exception)
85 | }
86 | }
87 |
88 | fun changeSchedule(changeSchedule: Schedule) =
89 | viewModelScope.launch {
90 | changeScheduleUseCase(changeSchedule)
91 | .onSuccess { isSuccess ->
92 | if (isSuccess) {
93 | logeukes { "update!" }
94 | }
95 | }
96 | .onFailure { exception ->
97 | logeukes(type = LoggerType.E) { exception }
98 | emitException(exception)
99 | }
100 | }
101 |
102 | fun deleteSchedule(schedule: Schedule) = viewModelScope.launch {
103 | deleteScheduleUseCase(schedule)
104 | .onSuccess { isSuccess ->
105 | if (isSuccess) {
106 | _schedules.update { it - schedule }
107 | }
108 | }
109 | .onFailure { exception ->
110 | logeukes(type = LoggerType.E) { exception }
111 | emitException(exception)
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/like/LikeFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TaskingFragment.kt] created by Ji Sungbin on 22. 1. 18. 오후 9:09
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main.fragment.like
11 |
12 | import androidx.fragment.app.activityViewModels
13 | import team.dahaeng.android.R
14 | import team.dahaeng.android.activity.base.BaseFragment
15 | import team.dahaeng.android.activity.main.MainViewModel
16 | import team.dahaeng.android.databinding.FragmentLikeBinding
17 |
18 | class LikeFragment : BaseFragment(R.layout.fragment_like) {
19 | override val vm: MainViewModel by activityViewModels()
20 | }
21 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/list/ListAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [PostAdapter.kt] created by Ji Sungbin on 22. 1. 19. 오후 4:28
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main.fragment.list
11 |
12 | import android.view.LayoutInflater
13 | import android.view.ViewGroup
14 | import androidx.recyclerview.widget.DiffUtil
15 | import androidx.recyclerview.widget.ListAdapter
16 | import androidx.recyclerview.widget.RecyclerView
17 | import team.dahaeng.android.databinding.LayoutPostBinding
18 | import team.dahaeng.android.domain.community.model.post.Post
19 |
20 | private typealias ListAdapterViewHolder = team.dahaeng.android.activity.main.fragment.list.ListAdapter.ViewHolder
21 |
22 | class ListAdapter(private val onPostClick: (Post) -> Unit) :
23 | ListAdapter(diffUtil) {
24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
25 | val binding = LayoutPostBinding.inflate(LayoutInflater.from(parent.context), parent, false)
26 | return ViewHolder(binding, onPostClick)
27 | }
28 |
29 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
30 | holder.bind(getItem(position))
31 | }
32 |
33 | class ViewHolder(
34 | private val binding: LayoutPostBinding,
35 | private val onPostClick: (Post) -> Unit,
36 | ) : RecyclerView.ViewHolder(binding.root) {
37 | fun bind(post: Post) {
38 | binding.run {
39 | this.post = post
40 | root.setOnClickListener {
41 | onPostClick(post)
42 | }
43 | }
44 | }
45 | }
46 |
47 | override fun getItemId(position: Int) = getItem(position).id
48 |
49 | override fun getItemCount() = currentList.count()
50 |
51 | companion object {
52 | private val diffUtil = object : DiffUtil.ItemCallback() {
53 | override fun areContentsTheSame(oldItem: Post, newItem: Post) =
54 | oldItem == newItem
55 |
56 | override fun areItemsTheSame(oldItem: Post, newItem: Post) =
57 | oldItem.id == newItem.id
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/list/ListFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TaskingFragment.kt] created by Ji Sungbin on 22. 1. 18. 오후 9:08
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main.fragment.list
11 |
12 | import android.location.Geocoder
13 | import android.location.Location
14 | import android.os.Bundle
15 | import android.view.View
16 | import androidx.fragment.app.activityViewModels
17 | import com.birjuvachhani.locus.Locus
18 | import io.github.jisungbin.logeukes.LoggerType
19 | import io.github.jisungbin.logeukes.logeukes
20 | import team.dahaeng.android.R
21 | import team.dahaeng.android.activity.base.BaseFragment
22 | import team.dahaeng.android.activity.main.MainViewModel
23 | import team.dahaeng.android.databinding.FragmentListBinding
24 | import team.dahaeng.android.util.test.TestUtil
25 | import java.util.Locale
26 |
27 | class ListFragment : BaseFragment(R.layout.fragment_list) {
28 |
29 | override val vm: MainViewModel by activityViewModels()
30 | private var lastestAddress = ""
31 |
32 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
33 | super.onViewCreated(view, savedInstanceState)
34 | lastestAddress = getString(R.string.fragment_list_loading_location)
35 |
36 | if (vm.lastLocate.isEmpty()) {
37 | Locus.startLocationUpdates(this) { result ->
38 | result.location?.let { location ->
39 | vm.lastLocate = location.tryParseAddress()
40 | binding.tvLocate.text = vm.lastLocate
41 | Locus.stopLocationUpdates()
42 | }
43 | result.error?.let { exception ->
44 | logeukes(type = LoggerType.E) { exception }
45 | }
46 | }
47 | } else {
48 | binding.tvLocate.text = vm.lastLocate
49 | }
50 |
51 | binding.rvPost.run {
52 | setHasFixedSize(true)
53 | setItemViewCacheSize(10)
54 | adapter = ListAdapter { post ->
55 | logeukes { "Post clicked: $post" }
56 | }.apply {
57 | submitList(TestUtil.posts())
58 | }
59 | }
60 |
61 | binding.tilSesarchContainer.setEndIconOnClickListener {
62 | // TODO
63 | }
64 | }
65 |
66 | private fun Location.tryParseAddress() = try {
67 | val geoCoder = Geocoder(requireContext().applicationContext, Locale.KOREA)
68 | val addressList = geoCoder.getFromLocation(latitude, longitude, 2)
69 | val address = addressList[1].getAddressLine(0).replace("대한민국 ", "")
70 | lastestAddress = address
71 | address
72 | } catch (exception: Exception) {
73 | logeukes(type = LoggerType.E) { exception }
74 | lastestAddress
75 | }
76 |
77 | override fun onPause() {
78 | Locus.stopLocationUpdates()
79 | super.onPause()
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/schedule/DetailScheduleFragment.kt:
--------------------------------------------------------------------------------
1 | package team.dahaeng.android.activity.main.fragment.schedule
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import androidx.fragment.app.activityViewModels
6 | import team.dahaeng.android.R
7 | import team.dahaeng.android.activity.base.BaseFragment
8 | import team.dahaeng.android.activity.main.MainViewModel
9 | import team.dahaeng.android.databinding.FragmentDeatilScheduleBinding
10 |
11 | class DetailScheduleFragment : BaseFragment(
12 | R.layout.fragment_deatil_schedule
13 | ){
14 | override val vm: MainViewModel by activityViewModels()
15 |
16 |
17 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
18 | super.onViewCreated(view, savedInstanceState)
19 | }
20 | }
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/schedule/ScheduleAdapter.kt:
--------------------------------------------------------------------------------
1 | package team.dahaeng.android.activity.main.fragment.schedule
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.DiffUtil
7 | import androidx.recyclerview.widget.ListAdapter
8 | import androidx.recyclerview.widget.RecyclerView
9 | import team.dahaeng.android.databinding.LayoutScheduleBinding
10 | import team.dahaeng.android.domain.community.model.schedule.Schedule
11 |
12 | class ScheduleAdapter(
13 | private val onMoreClick: (View, Schedule) -> Unit,
14 | private val onClick: (View, Schedule) -> Unit
15 | ) :
16 | ListAdapter(diffUtil) {
17 |
18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
19 | val binding =
20 | LayoutScheduleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
21 | return ViewHolder(binding, onMoreClick, onClick)
22 | }
23 |
24 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
25 | holder.bind(getItem(position))
26 | }
27 |
28 | class ViewHolder(
29 | private val binding: LayoutScheduleBinding,
30 | private val onMoreClick: (View, Schedule) -> Unit,
31 | private val onClick: (View, Schedule) -> Unit
32 | ) : RecyclerView.ViewHolder(binding.root) {
33 | fun bind(schedule: Schedule) {
34 | binding.schedule = schedule
35 | binding.ivMore.setOnClickListener { view ->
36 | onMoreClick(view, schedule)
37 | }
38 | binding.tvTitle.setOnClickListener { view ->
39 | onClick(view, schedule)
40 | }
41 | }
42 | }
43 |
44 | override fun getItemId(position: Int) = getItem(position).id
45 |
46 | override fun getItemCount() = currentList.count()
47 |
48 | private companion object {
49 | val diffUtil = object : DiffUtil.ItemCallback() {
50 | override fun areContentsTheSame(oldItem: Schedule, newItem: Schedule) =
51 | oldItem.id == newItem.id
52 |
53 | override fun areItemsTheSame(oldItem: Schedule, newItem: Schedule) =
54 | oldItem == newItem
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/main/fragment/schedule/ScheduleFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TaskingFragment.kt] created by Ji Sungbin on 22. 1. 17. 오전 9:56
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.main.fragment.schedule
11 |
12 | import android.content.Intent
13 | import android.os.Bundle
14 | import android.view.View
15 | import androidx.appcompat.widget.PopupMenu
16 | import androidx.fragment.app.activityViewModels
17 | import androidx.navigation.fragment.findNavController
18 | import io.github.jisungbin.logeukes.logeukes
19 | import team.dahaeng.android.R
20 | import team.dahaeng.android.activity.base.BaseFragment
21 | import team.dahaeng.android.activity.createschedule.CreateScheduleActivity
22 | import team.dahaeng.android.activity.main.MainViewModel
23 | import team.dahaeng.android.activity.modifyschedule.ModifyScheduleActivity
24 | import team.dahaeng.android.data.DataStore
25 | import team.dahaeng.android.databinding.FragmentScheduleBinding
26 | import team.dahaeng.android.domain.community.model.schedule.Schedule
27 | import team.dahaeng.android.util.extensions.collectWithLifecycle
28 |
29 | class ScheduleFragment : BaseFragment(
30 | R.layout.fragment_schedule
31 | ) {
32 |
33 | private val adapter by lazy {
34 | ScheduleAdapter(onClick = { _, _ ->
35 | findNavController().navigate(R.id.detailScheduleFragment)
36 | }, onMoreClick = { view, schedule ->
37 | openMorePopup(view, schedule)
38 | })
39 | }
40 | override val vm: MainViewModel by activityViewModels()
41 |
42 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
43 | super.onViewCreated(view, savedInstanceState)
44 |
45 | binding.rvSchedule.run {
46 | setHasFixedSize(true)
47 | setItemViewCacheSize(10)
48 | adapter = this@ScheduleFragment.adapter.apply {
49 | submitList(DataStore.schedules)
50 | }
51 | }
52 |
53 | vm.schedules.collectWithLifecycle(viewLifecycleOwner) { scheduleList ->
54 | logeukes { scheduleList }
55 | adapter.submitList(scheduleList)
56 | }
57 |
58 | binding.fabNewSchedule.setOnClickListener {
59 | startActivity(Intent(context, CreateScheduleActivity::class.java))
60 | }
61 | }
62 |
63 | private fun openMorePopup(view: View, schedule: Schedule) {
64 | PopupMenu(requireActivity(), view).apply {
65 | setOnMenuItemClickListener { item ->
66 | when (item.itemId) {
67 | R.id.menu_share -> {
68 | // TODO: 카카오톡 공유
69 | logeukes { "공유" }
70 | true
71 | }
72 | R.id.menu_modify -> {
73 | val intent = Intent(context, ModifyScheduleActivity::class.java)
74 | intent.putExtra("modifyschedule", schedule)
75 | startActivity(intent)
76 | true
77 | }
78 | R.id.menu_delete -> {
79 | vm.deleteSchedule(schedule)
80 | true
81 | }
82 | else -> false
83 | }
84 | }
85 | inflate(R.menu.schedule_menu)
86 | show()
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/ModifyCourseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ModifyCourseActivity.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.modifyschedule
11 |
12 | import android.app.Activity
13 | import android.content.Intent
14 | import android.os.Bundle
15 | import androidx.activity.viewModels
16 | import androidx.recyclerview.widget.DividerItemDecoration
17 | import androidx.recyclerview.widget.ItemTouchHelper
18 | import androidx.recyclerview.widget.RecyclerView
19 | import dagger.hilt.android.AndroidEntryPoint
20 | import team.dahaeng.android.R
21 | import team.dahaeng.android.activity.base.BaseActivity
22 | import team.dahaeng.android.databinding.ActivityModifyCourseBinding
23 | import team.dahaeng.android.domain.community.model.travel.CourseList
24 |
25 | @AndroidEntryPoint
26 | class ModifyCourseActivity : BaseActivity(
27 | R.layout.activity_modify_course
28 | ) {
29 |
30 | override val vm: ModifyScheduleViewModel by viewModels()
31 |
32 | override fun onCreate(savedInstanceState: Bundle?) {
33 | super.onCreate(savedInstanceState)
34 |
35 | val courseList = intent.getSerializableExtra("modifycourselist") as CourseList
36 |
37 | binding.rvModifyCourse.run {
38 |
39 | setHasFixedSize(true)
40 | setItemViewCacheSize(10)
41 | addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
42 | adapter = ModifyCourseAdapter(
43 | ).apply {
44 | submitList(courseList.courses)
45 | }
46 | setItemTouchCallback()
47 | }
48 |
49 | binding.btnComplete.setOnClickListener {
50 | val intent = Intent(applicationContext, ModifyScheduleActivity::class.java).apply {
51 | val list =
52 | (binding.rvModifyCourse.adapter as ModifyCourseAdapter).currentList.toMutableList()
53 | courseList.courses = list
54 | putExtra("modifycourselistresult", courseList)
55 | }
56 | setResult(Activity.RESULT_OK, intent)
57 | finish()
58 | }
59 | }
60 |
61 | private fun setItemTouchCallback() {
62 | val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
63 | ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.LEFT
64 | ) {
65 | override fun onMove(
66 | recyclerView: RecyclerView,
67 | viewHolder: RecyclerView.ViewHolder,
68 | target: RecyclerView.ViewHolder
69 | ): Boolean {
70 | val fromPos: Int = viewHolder.absoluteAdapterPosition
71 | val toPos: Int = target.absoluteAdapterPosition
72 | (binding.rvModifyCourse.adapter as ModifyCourseAdapter).swapItem(fromPos, toPos)
73 | return true
74 | }
75 |
76 | override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
77 | (binding.rvModifyCourse.adapter as ModifyCourseAdapter).removeItem(viewHolder.layoutPosition)
78 | }
79 |
80 | }
81 | ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.rvModifyCourse)
82 | }
83 | }
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/ModifyCourseAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ModifyCourseAdapter.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.modifyschedule
11 |
12 | import android.view.LayoutInflater
13 | import android.view.ViewGroup
14 | import androidx.recyclerview.widget.DiffUtil
15 | import androidx.recyclerview.widget.ListAdapter
16 | import androidx.recyclerview.widget.RecyclerView
17 | import team.dahaeng.android.databinding.LayoutModifyCourseBinding
18 | import team.dahaeng.android.domain.community.model.travel.Course
19 | import java.util.*
20 |
21 | class ModifyCourseAdapter :
22 | ListAdapter(diffUtil) {
23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
24 | val binding =
25 | LayoutModifyCourseBinding.inflate(LayoutInflater.from(parent.context), parent, false)
26 | return ViewHolder(binding)
27 | }
28 |
29 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
30 | holder.bind(getItem(position))
31 | // TODO: imageview glide
32 | // TODO: buttons image set
33 | // TODO: buttons onclickListener
34 |
35 | }
36 |
37 | fun swapItem(fromPos : Int, toPos : Int){
38 | val list = currentList.toMutableList()
39 | Collections.swap(list, fromPos, toPos)
40 | submitList(list)
41 | }
42 |
43 | fun removeItem(position: Int) {
44 | val list = currentList.toMutableList()
45 | list.removeAt(position)
46 | submitList(list)
47 | }
48 |
49 | class ViewHolder(
50 | private val binding: LayoutModifyCourseBinding
51 | ) : RecyclerView.ViewHolder(binding.root) {
52 | fun bind(course : Course){
53 | binding.course = course
54 | }
55 | }
56 |
57 | private companion object {
58 | val diffUtil = object : DiffUtil.ItemCallback() {
59 | override fun areContentsTheSame(oldItem: Course, newItem: Course) =
60 | oldItem == newItem
61 |
62 | override fun areItemsTheSame(oldItem: Course, newItem: Course) =
63 | oldItem == newItem
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/ModifyScheduleActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ModifyScheduleActivity.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.modifyschedule
11 |
12 |
13 | import android.app.Activity
14 | import android.content.Intent
15 | import android.os.Bundle
16 | import android.widget.ArrayAdapter
17 | import androidx.activity.result.contract.ActivityResultContracts
18 | import androidx.activity.viewModels
19 | import androidx.core.util.Pair
20 | import com.google.android.material.datepicker.MaterialDatePicker
21 | import dagger.hilt.android.AndroidEntryPoint
22 | import team.dahaeng.android.R
23 | import team.dahaeng.android.activity.base.BaseActivity
24 | import team.dahaeng.android.databinding.ActivityModifyScheduleBinding
25 | import team.dahaeng.android.domain.community.model.schedule.Schedule
26 | import team.dahaeng.android.domain.community.model.travel.CourseList
27 | import team.dahaeng.android.domain.community.model.travel.Period
28 | import team.dahaeng.android.domain.community.model.travel.Theme
29 | import team.dahaeng.android.domain.community.model.travel.Travel
30 | import java.text.SimpleDateFormat
31 | import java.util.*
32 |
33 | @AndroidEntryPoint
34 | class ModifyScheduleActivity : BaseActivity(
35 | R.layout.activity_modify_schedule
36 | ) {
37 |
38 | override val vm: ModifyScheduleViewModel by viewModels()
39 |
40 | override fun onCreate(savedInstanceState: Bundle?) {
41 | super.onCreate(savedInstanceState)
42 |
43 | binding.schedule = intent.getSerializableExtra("modifyschedule") as Schedule
44 | val schedule = binding.schedule
45 | var changeCourseList = CourseList()
46 | binding.period = schedule!!.travel.totalPeriod
47 |
48 | binding.snTheme.adapter = ArrayAdapter.createFromResource(
49 | this,
50 | R.array.modify_schedule_theme_array,
51 | android.R.layout.simple_dropdown_item_1line
52 | )
53 |
54 | val startForResult =
55 | registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
56 | if (result.resultCode == Activity.RESULT_OK) {
57 | val intent = result.data
58 | changeCourseList =
59 | (intent!!.getSerializableExtra("modifycourselistresult") as CourseList)
60 | }
61 | }
62 |
63 | binding.rvModifySchedule.run {
64 | setHasFixedSize(true)
65 | setItemViewCacheSize(10)
66 | adapter = ModifyScheduleAdapter(
67 | onEditClick = { _, courseList ->
68 | val intent = Intent(context, ModifyCourseActivity::class.java)
69 | intent.putExtra("modifycourselist", courseList)
70 | startForResult.launch(intent)
71 | courseList.courses = changeCourseList.courses
72 | }
73 | ).apply {
74 | submitList(schedule.travel.courseLists)
75 | }
76 | }
77 | binding.snTheme.adapter = ArrayAdapter.createFromResource(
78 | this,
79 | R.array.modify_schedule_theme_array,
80 | android.R.layout.simple_dropdown_item_1line
81 | )
82 | binding.snTheme.setSelection(getThemePosition(schedule.travel.theme.value))
83 | binding.tvTotalperiodselect.setOnClickListener {
84 | showDatePicker()
85 | }
86 | binding.btnComplete.setOnClickListener {
87 | schedule.title = binding.etTitle.text.toString()
88 | schedule.travel = Travel(
89 | theme = Theme(
90 | binding.snTheme.selectedItem.toString()
91 | ),
92 | commonAddress = binding.etCommonaddress.text.toString(),
93 | totalPeriod = binding.period as Period,
94 | totalPrice = binding.etTotalprice.text.toString().toInt(),
95 | courseLists = (binding.rvModifySchedule.adapter as ModifyScheduleAdapter).currentList
96 | )
97 |
98 | // Todo : change schedule in firestore
99 | // vm.changeSchedule(schedule)
100 | finish()
101 | }
102 | }
103 |
104 | private fun getThemePosition(theme: String): Int {
105 | when (theme) {
106 | "펜션" -> {
107 | return 0
108 | }
109 | "캠핑" -> {
110 | return 1
111 | }
112 | "스포츠" -> {
113 | return 2
114 | }
115 | "힐링" -> {
116 | return 3
117 | }
118 | "바다" -> {
119 | return 4
120 | }
121 | "산" -> {
122 | return 5
123 | }
124 | "음식" -> {
125 | return 6
126 | }
127 | "명소" -> {
128 | return 7
129 | }
130 | }
131 | return 0
132 | }
133 |
134 | private fun showDatePicker() {
135 | val dateRangePicker = MaterialDatePicker.Builder.dateRangePicker().apply {
136 | setTitleText("기간을 선택하세요")
137 | setSelection(
138 | Pair(
139 | MaterialDatePicker.thisMonthInUtcMilliseconds(),
140 | MaterialDatePicker.todayInUtcMilliseconds()
141 | )
142 | )
143 | }.build()
144 | dateRangePicker.apply {
145 | show(supportFragmentManager, "date_picker")
146 | addOnNegativeButtonClickListener { dateRangePicker.dismiss() }
147 | addOnPositiveButtonClickListener {
148 | val startDate = SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(it.first)
149 | val endDate = SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(it.second)
150 | binding.period = Period(endDate.toLong(), startDate.toLong())
151 |
152 | }
153 | }
154 | }
155 | }
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/ModifyScheduleAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ModifyScheduleAdapter.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.modifyschedule
11 |
12 | import android.view.LayoutInflater
13 | import android.view.View
14 | import android.view.ViewGroup
15 | import androidx.recyclerview.widget.DiffUtil
16 | import androidx.recyclerview.widget.ListAdapter
17 | import androidx.recyclerview.widget.RecyclerView
18 | import team.dahaeng.android.databinding.LayoutRvModfiyScheduleItemBinding
19 | import team.dahaeng.android.domain.community.model.travel.CourseList
20 |
21 | class ModifyScheduleAdapter(
22 | private val onEditClick: (View, CourseList) -> Unit
23 | ) :
24 | ListAdapter(diffUtil) {
25 |
26 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
27 | val binding =
28 | LayoutRvModfiyScheduleItemBinding.inflate(
29 | LayoutInflater.from(parent.context),
30 | parent,
31 | false
32 | )
33 | return ViewHolder(binding, onEditClick)
34 | }
35 |
36 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
37 | holder.bind(getItem(position))
38 | holder.coursepositionTextview.text = "코스 " + (position + 1)
39 | }
40 |
41 | class ViewHolder(
42 | private val binding: LayoutRvModfiyScheduleItemBinding,
43 | private val onEditClick: (View, CourseList) -> Unit
44 | ) : RecyclerView.ViewHolder(binding.root) {
45 | val coursepositionTextview = binding.tvCourse
46 |
47 | fun bind(courseList: CourseList) {
48 | binding.rvHorizontal.adapter = PlaceAdapter().apply {
49 | submitList(courseList.courses)
50 | }
51 | binding.ibEdit.setOnClickListener { view ->
52 | onEditClick(view, courseList)
53 | }
54 | }
55 | }
56 |
57 |
58 | override fun getItemCount() = currentList.count()
59 |
60 | private companion object {
61 | val diffUtil = object : DiffUtil.ItemCallback() {
62 | override fun areContentsTheSame(oldItem: CourseList, newItem: CourseList) =
63 | oldItem == newItem
64 |
65 | override fun areItemsTheSame(oldItem: CourseList, newItem: CourseList) =
66 | oldItem == newItem
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/ModifyScheduleViewModel.kt:
--------------------------------------------------------------------------------
1 | package team.dahaeng.android.activity.modifyschedule
2 |
3 | import team.dahaeng.android.activity.base.BaseViewModel
4 |
5 | class ModifyScheduleViewModel : BaseViewModel() {
6 | }
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/modifyschedule/PlaceAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [PlaceAdapter.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.modifyschedule
11 |
12 | import android.view.LayoutInflater
13 | import android.view.ViewGroup
14 | import androidx.recyclerview.widget.DiffUtil
15 | import androidx.recyclerview.widget.ListAdapter
16 | import androidx.recyclerview.widget.RecyclerView
17 | import team.dahaeng.android.databinding.LayoutModifyScheduleBinding
18 |
19 | import team.dahaeng.android.domain.community.model.travel.Course
20 |
21 | class PlaceAdapter :
22 | ListAdapter(diffUtil) {
23 |
24 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
25 | val binding =
26 | LayoutModifyScheduleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
27 | return ViewHolder(binding)
28 | }
29 |
30 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
31 | holder.bind(getItem(position))
32 | // photoIv glide
33 |
34 | // transportationIv, accommodationIv image set
35 | // transportationIv, accommodationIv onclick
36 |
37 | }
38 |
39 | class ViewHolder(
40 | private val binding: LayoutModifyScheduleBinding,
41 | ) : RecyclerView.ViewHolder(binding.root) {
42 |
43 | val photoIv = binding.ivPhoto
44 | val transportationIv = binding.ivTransportation
45 | val accommodationIv = binding.ivAccommodation
46 |
47 | fun bind(course : Course) {
48 | binding.course = course
49 | }
50 | }
51 |
52 |
53 | override fun getItemCount() = currentList.count()
54 |
55 | private companion object {
56 | val diffUtil = object : DiffUtil.ItemCallback() {
57 | override fun areContentsTheSame(oldItem: Course, newItem: Course) =
58 | oldItem == newItem
59 |
60 | override fun areItemsTheSame(oldItem: Course, newItem: Course) =
61 | oldItem == newItem
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/tasking/TaskingActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TaskingActivity.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.tasking
11 |
12 | import androidx.activity.viewModels
13 | import dagger.hilt.android.AndroidEntryPoint
14 | import team.dahaeng.android.R
15 | import team.dahaeng.android.activity.base.BaseActivity
16 | import team.dahaeng.android.databinding.ActivityTaskingBinding
17 |
18 | @AndroidEntryPoint
19 | class TaskingActivity : BaseActivity(
20 | R.layout.activity_tasking
21 | ) {
22 | override val vm: TaskingViewModel by viewModels()
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/activity/tasking/TaskingViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TaskingViewModel.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.activity.tasking
11 |
12 | import dagger.hilt.android.lifecycle.HiltViewModel
13 | import team.dahaeng.android.activity.base.BaseViewModel
14 | import javax.inject.Inject
15 |
16 | @HiltViewModel
17 | class TaskingViewModel @Inject constructor() : BaseViewModel()
18 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/data/DataStore.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Store.kt] created by Ji Sungbin on 22. 1. 13. 오후 7:51
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.data
11 |
12 | import team.dahaeng.android.domain.aouth.model.User
13 | import team.dahaeng.android.domain.community.model.post.Post
14 | import team.dahaeng.android.domain.community.model.schedule.Schedule
15 |
16 | // TODO: 이게 맞나?? ㅋㅋ
17 | @Suppress("ObjectPropertyName")
18 | object DataStore {
19 | lateinit var me: User
20 |
21 | private val _posts = mutableListOf()
22 | val posts: List get() = _posts
23 |
24 | private val _schedules = mutableListOf()
25 | val schedules: List get() = _schedules
26 |
27 | fun updatePosts(posts: List) {
28 | _posts.addAll(posts)
29 | }
30 |
31 | fun updateSchedules(schedules: List) {
32 | _schedules.addAll(schedules)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/di/common/SharedPreferencesModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [SharedPreferenceModule.kt] created by Ji Sungbin on 22. 1. 18. 오후 6:04
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.di.common
11 |
12 | import android.content.Context
13 | import android.content.SharedPreferences
14 | import dagger.Module
15 | import dagger.Provides
16 | import dagger.hilt.InstallIn
17 | import dagger.hilt.android.qualifiers.ApplicationContext
18 | import dagger.hilt.components.SingletonComponent
19 | import javax.inject.Singleton
20 |
21 | @Module
22 | @InstallIn(SingletonComponent::class)
23 | object SharedPreferencesModule {
24 | private const val SharedPreferencesKey = "dahaeng-pref"
25 |
26 | @Provides
27 | @Singleton
28 | fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences =
29 | context.getSharedPreferences(SharedPreferencesKey, Context.MODE_PRIVATE)
30 | }
31 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/di/repository/RepositoryModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [RepositoryModule.kt] created by Ji Sungbin on 22. 1. 6. 오전 3:01
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.di.repository
11 |
12 | import dagger.Module
13 | import dagger.Provides
14 | import dagger.hilt.InstallIn
15 | import dagger.hilt.android.components.ViewModelComponent
16 | import dagger.hilt.android.scopes.ViewModelScoped
17 | import team.dahaeng.android.data.aouth.repository.AouthRepositoryImpl
18 | import team.dahaeng.android.data.community.repository.FirebaseRepositoryImpl
19 | import team.dahaeng.android.domain.aouth.repository.AouthRepository
20 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
21 |
22 | @Module
23 | @InstallIn(ViewModelComponent::class)
24 | object RepositoryModule {
25 | @Provides
26 | @ViewModelScoped
27 | fun provideAouthRepository(): AouthRepository = AouthRepositoryImpl()
28 |
29 | @Provides
30 | @ViewModelScoped
31 | fun provideFirebaseRepository(): FirebaseRepository = FirebaseRepositoryImpl()
32 | }
33 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/di/usecase/AouthUseCaseModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [AouthUseCaseModule.kt] created by Ji Sungbin on 22. 1. 6. 오전 4:21
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.di.usecase
11 |
12 | import android.content.Context
13 | import dagger.Module
14 | import dagger.Provides
15 | import dagger.hilt.InstallIn
16 | import dagger.hilt.android.components.ViewModelComponent
17 | import dagger.hilt.android.qualifiers.ApplicationContext
18 | import dagger.hilt.android.scopes.ViewModelScoped
19 | import team.dahaeng.android.domain.aouth.repository.AouthRepository
20 | import team.dahaeng.android.domain.aouth.usecase.KakaoLoginUseCase
21 |
22 | @Module
23 | @InstallIn(ViewModelComponent::class)
24 | object AouthUseCaseModule {
25 | @Provides
26 | @ViewModelScoped
27 | fun provideKakaoLoginUseCase(
28 | repository: AouthRepository,
29 | @ApplicationContext context: Context,
30 | ): KakaoLoginUseCase = KakaoLoginUseCase(repository, context)
31 | }
32 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/di/usecase/CommunityUseCaseModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [CommunityUseCaseModule.kt] created by 210202
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.di.usecase
11 |
12 | import dagger.Module
13 | import dagger.Provides
14 | import dagger.hilt.InstallIn
15 | import dagger.hilt.android.components.ViewModelComponent
16 | import dagger.hilt.android.scopes.ViewModelScoped
17 | import team.dahaeng.android.domain.community.repository.FirebaseRepository
18 | import team.dahaeng.android.domain.community.usecase.post.ImportPostsUseCase
19 | import team.dahaeng.android.domain.community.usecase.post.UploadImageUseCase
20 | import team.dahaeng.android.domain.community.usecase.post.UploadPostUseCase
21 | import team.dahaeng.android.domain.community.usecase.schedule.ChangeScheduleUseCase
22 | import team.dahaeng.android.domain.community.usecase.schedule.DeleteScheduleUseCase
23 | import team.dahaeng.android.domain.community.usecase.schedule.ImportScheduleUseCase
24 | import team.dahaeng.android.domain.community.usecase.schedule.UploadScheduleUseCase
25 |
26 | @Module
27 | @InstallIn(ViewModelComponent::class)
28 | object CommunityUseCaseModule {
29 | @Provides
30 | @ViewModelScoped
31 | fun provideUploadImageUseCase(repository: FirebaseRepository): UploadImageUseCase =
32 | UploadImageUseCase(repository)
33 |
34 | @Provides
35 | @ViewModelScoped
36 | fun provideUploadPostUseCase(repository: FirebaseRepository): UploadPostUseCase =
37 | UploadPostUseCase(repository)
38 |
39 | @Provides
40 | @ViewModelScoped
41 | fun provideImportPostsUseCaseToViewModel(repository: FirebaseRepository): ImportPostsUseCase =
42 | ImportPostsUseCase(repository)
43 |
44 | @Provides
45 | @ViewModelScoped
46 | fun provideUploadScheduleUseCase(reposiotry: FirebaseRepository): UploadScheduleUseCase =
47 | UploadScheduleUseCase(reposiotry)
48 |
49 | @Provides
50 | @ViewModelScoped
51 | fun provideImportScheduleUseCase(repository: FirebaseRepository): ImportScheduleUseCase =
52 | ImportScheduleUseCase(repository)
53 |
54 | @Provides
55 | @ViewModelScoped
56 | fun provideDeleteScheduleUseCase(reposiotry: FirebaseRepository): DeleteScheduleUseCase =
57 | DeleteScheduleUseCase(reposiotry)
58 |
59 | @Provides
60 | @ViewModelScoped
61 | fun provideChangeScheduleUseCase(repository: FirebaseRepository): ChangeScheduleUseCase =
62 | ChangeScheduleUseCase(repository)
63 | }
64 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/ui/databinding/ImageViewAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [ImageViewAdapter.kt] created by Ji Sungbin on 22. 1. 19. 오후 2:06
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.ui.databinding
11 |
12 | import android.widget.ImageView
13 | import androidx.databinding.BindingAdapter
14 | import androidx.lifecycle.findViewTreeLifecycleOwner
15 | import coil.loadAny
16 | import coil.request.CachePolicy
17 | import team.dahaeng.android.R
18 |
19 | @BindingAdapter("with_coil_small")
20 | fun loadSrcWithCoilSmallSize(view: ImageView, src: Any) {
21 | view.loadAny(src) {
22 | crossfade(true)
23 | placeholder(R.drawable.ic_round_airplane_ticket_24)
24 | lifecycle(view.findViewTreeLifecycleOwner())
25 | allowRgb565(true)
26 | diskCachePolicy(CachePolicy.ENABLED)
27 | }
28 | }
29 |
30 | @BindingAdapter("with_coil_big")
31 | fun loadSrcWithCoilBigSize(view: ImageView, src: Any) {
32 | view.loadAny(src) {
33 | crossfade(true)
34 | placeholder(R.drawable.ic_round_airplane_ticket_24)
35 | lifecycle(view.findViewTreeLifecycleOwner())
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/NetworkUtil.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [NetworkUtil.kt] created by Ji Sungbin on 22. 1. 19. 오전 11:48
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util
11 |
12 | import android.annotation.SuppressLint
13 | import android.content.Context
14 | import android.net.ConnectivityManager
15 | import android.net.NetworkCapabilities
16 |
17 | object NetworkUtil {
18 | @SuppressLint("MissingPermission")
19 | fun isNetworkAvailable(context: Context) =
20 | (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
21 | getNetworkCapabilities(activeNetwork)?.run {
22 | hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
23 | hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
24 | hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
25 | } ?: false
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/constants/Key.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [SharedPreferences.kt] created by Ji Sungbin on 22. 1. 18. 오후 6:12
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.constants
11 |
12 | object Key {
13 | object User {
14 | const val KakaoProfile = "user-kakao-profile"
15 | }
16 |
17 | object Intent {
18 | const val Error = "intent-error"
19 | const val NoInternet = "intent-no-internet"
20 | const val Exception = "intent-exception"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/extensions/Flow.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [Flow.kt] created by Ji Sungbin on 22. 1. 13. 오후 8:20
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.extensions
11 |
12 | import androidx.lifecycle.LifecycleOwner
13 | import androidx.lifecycle.flowWithLifecycle
14 | import androidx.lifecycle.lifecycleScope
15 | import kotlinx.coroutines.flow.Flow
16 |
17 | fun Flow.collectWithLifecycle(
18 | lifecycleOwner: LifecycleOwner,
19 | action: suspend (T) -> Unit,
20 | ) {
21 | lifecycleOwner.lifecycleScope.launchWhenCreated {
22 | flowWithLifecycle(lifecycleOwner.lifecycle).collect { value ->
23 | action(value)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/extensions/LifeCycle.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [LifeCycle.kt] created by Ji Sungbin on 22. 1. 5. 오후 9:20
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.extensions
11 |
12 | import androidx.lifecycle.LifecycleOwner
13 | import androidx.lifecycle.lifecycleScope
14 | import kotlinx.coroutines.delay
15 |
16 | fun LifecycleOwner.doDelayed(ms: Long, action: suspend () -> Unit) {
17 | lifecycleScope.launchWhenCreated {
18 | delay(ms)
19 | action()
20 | }
21 | }
22 |
23 | fun LifecycleOwner.launchedWhenCreated(action: suspend () -> Unit) {
24 | lifecycleScope.launchWhenCreated {
25 | action()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/extensions/SharedPreferences.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [SharedPreferences.kt] created by Ji Sungbin on 22. 1. 18. 오후 6:09
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.extensions
11 |
12 | import android.content.SharedPreferences
13 | import androidx.core.content.edit
14 |
15 | operator fun SharedPreferences.get(name: String, default: String? = null) = getString(name, default)
16 |
17 | operator fun SharedPreferences.set(name: String, value: String) = edit { putString(name, value) }
18 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/extensions/json.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [json.kt] created by Ji Sungbin on 22. 1. 18. 오후 6:57
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.extensions
11 |
12 | import com.fasterxml.jackson.databind.DeserializationFeature
13 | import com.fasterxml.jackson.databind.ObjectMapper
14 | import com.fasterxml.jackson.module.kotlin.registerKotlinModule
15 |
16 | @PublishedApi
17 | internal val mapper by lazy {
18 | ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
19 | .registerKotlinModule()
20 | }
21 |
22 | inline fun String.toModel(): T = mapper.readValue(this, T::class.java)
23 | ?: throw Exception("문자열을 json 모델로 바꾸는데 오류가 발생했어요.\n\n($this)")
24 |
25 | fun Any.toJsonString() = mapper.writeValueAsString(this)
26 | ?: throw Exception("json 모델을 문자열로 바꾸는데 오류가 발생했어요.\n\n($this)")
27 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/extensions/toast.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [toast.kt] created by Ji Sungbin
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.extensions
11 |
12 | import android.app.Activity
13 | import android.content.Context
14 | import android.widget.Toast
15 | import androidx.fragment.app.Fragment
16 |
17 | fun toast(context: Context, message: String, length: Int) {
18 | Toast.makeText(context, message, length).show()
19 | }
20 |
21 | fun toast(activity: Activity, message: String, length: Int) {
22 | activity.runOnUiThread {
23 | Toast.makeText(activity, message, length).show()
24 | }
25 | }
26 |
27 | fun Fragment.toast(message: String, length: Int = Toast.LENGTH_SHORT) {
28 | toast(requireActivity(), message, length)
29 | }
30 |
31 | @JvmName("ActivityToastExtension")
32 | fun Activity.toast(message: String, length: Int = Toast.LENGTH_SHORT) {
33 | toast(this, message, length)
34 | }
35 |
--------------------------------------------------------------------------------
/presentation/src/main/kotlin/team/dahaeng/android/util/test/TestUtil.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Dahaeng © 2022 Ji Sungbin, 210202. all rights reserved.
3 | * Dahaeng license is under the MIT.
4 | *
5 | * [TestUtil.kt] created by Ji Sungbin on 22. 1. 19. 오후 5:13
6 | *
7 | * Please see: https://github.com/dahaeng/dahaeng-android/blob/main/LICENSE.
8 | */
9 |
10 | package team.dahaeng.android.util.test
11 |
12 | import team.dahaeng.android.domain.community.model.post.Post
13 | import team.dahaeng.android.domain.community.model.travel.Period
14 | import team.dahaeng.android.domain.community.model.travel.Target
15 | import team.dahaeng.android.domain.community.model.travel.Theme
16 | import team.dahaeng.android.domain.community.model.travel.Transportation
17 | import team.dahaeng.android.domain.community.model.travel.Travel
18 | import team.dahaeng.android.domain.community.model.schedule.Schedule
19 | import java.util.Date
20 | import kotlin.random.Random
21 |
22 | object TestUtil {
23 | private const val TestImageUrl =
24 | "https://images.unsplash.com/photo-1523906834658-6e24ef2386f9?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1283&q=80"
25 |
26 | /* fun posts(count: Int = 10) = List(count) { index ->
27 | Post(
28 | title = "여행지 - $index",
29 | content = "이것은 아름다운 ${index}번째 여행지 입니다.",
30 | travel = Travel(
31 | totalPrice = Random.nextLong(10_000, 1_000_000_000),
32 | transportation = Transportation.Random,
33 | period = Period(from = "어제", to = "내일"),
34 | places = listOf(),
35 | photos = listOf(TestImageUrl),
36 | theme = Theme.Random,
37 | target = Target.Random,
38 | commonAddress = "서울시 한강로"
39 | ),
40 | createdAt = Date().time
41 | )
42 | }
43 |
44 | fun schedules(count: Int = 10) = List(count) { index ->
45 | Schedule(
46 | participant = listOf(),
47 | title = "제주 레포츠렌드 - $index",
48 | theme = "",
49 | totalPrice = 0,
50 | transportation = "",
51 | period = Period(from = "", to = ""),
52 | photos = listOf(),
53 | places = listOf(),
54 | accommodation = ""
55 | )
56 | }
57 | */
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/bg_intro_thumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/drawable/bg_intro_thumbnail.png
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/bg_rounded_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/bg_rounded_lightblue.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_baseline_edit_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_baseline_more_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_baseline_post_add_24.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_baseline_reorder_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_outline_location_on_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_airplane_ticket_24.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_card_travel_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_castle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_favorite_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_filter_list_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_search_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_round_star_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/presentation/src/main/res/drawable/ic_splash_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/drawable/ic_splash_logo.png
--------------------------------------------------------------------------------
/presentation/src/main/res/font/nanumbarungothic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/font/nanumbarungothic.ttf
--------------------------------------------------------------------------------
/presentation/src/main/res/font/nanumbarunpen_b.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/font/nanumbarunpen_b.ttf
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/activity_error.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
37 |
38 |
46 |
47 |
55 |
56 |
62 |
63 |
64 |
65 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
21 |
22 |
29 |
30 |
37 |
38 |
49 |
50 |
61 |
62 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
33 |
34 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/activity_modify_course.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
31 |
32 |
40 |
41 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/activity_tasking.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
22 |
23 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/fragment_deatil_schedule.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/fragment_like.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
27 |
28 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/fragment_list.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
23 |
24 |
25 |
33 |
34 |
44 |
45 |
63 |
64 |
76 |
77 |
98 |
99 |
108 |
109 |
110 |
111 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/fragment_schedule.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
27 |
28 |
39 |
40 |
55 |
56 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_avatar.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_modify_course.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
27 |
28 |
42 |
43 |
52 |
53 |
63 |
64 |
74 |
75 |
85 |
86 |
97 |
98 |
109 |
110 |
120 |
121 |
130 |
131 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_modify_schedule.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
26 |
27 |
42 |
43 |
52 |
53 |
63 |
64 |
74 |
75 |
85 |
86 |
96 |
97 |
108 |
109 |
119 |
120 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_post.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
28 |
29 |
37 |
38 |
45 |
46 |
55 |
56 |
60 |
61 |
71 |
72 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_rv_modfiy_schedule_item.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
30 |
31 |
32 |
33 |
42 |
43 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/presentation/src/main/res/layout/layout_schedule.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
26 |
27 |
39 |
40 |
51 |
52 |
63 |
64 |
79 |
80 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/presentation/src/main/res/menu/main_menu.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/presentation/src/main/res/menu/schedule_menu.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/presentation/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/presentation/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/presentation/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/presentation/src/main/res/navigation/main_navigation.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
15 |
16 |
20 |
21 |
25 |
26 |
30 |
33 |
34 |
38 |
39 |
--------------------------------------------------------------------------------
/presentation/src/main/res/values-v27/themes.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/presentation/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/presentation/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | #faa376
12 | #c47449
13 | #ffd5a5
14 |
15 | #ffffff
16 | #000000
17 |
18 | #eeeeee
19 | #2630d4
20 | #969ad9
21 |
--------------------------------------------------------------------------------
/presentation/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | …
12 | 다행
13 | 다같이 정하는 여행 계획
14 |
15 | 위치 권한 필요
16 | 현재 위치에 맞는 여행지를 추천해드리기 위해 위치 권한이 필요해요.
17 | 위치 권한 거절됨
18 | 현재 위치를 불러올 수 잆어요.\n여행지 추천이 랜덤으로 진행돼요.
19 | 위치 사용 불가
20 | 현재 시스템의 위치 기능이 꺼져있어요.\n내 위치에 맞는 최적화된 여행지를 추천받기 위해 위치 기능을 사용해 주세요.
21 |
22 | 여행지
23 | 좋아요
24 | 내 여행
25 |
26 | 카카오톡으로 시작하기
27 | 앱 시작에 실패했어요 😢\n잠시후 다시 시도해 주세요.
28 | 첫 로그인을 환영해요 🥰
29 |
30 | 알 수 없는 오류가 발생했어요
31 | 인터넷이 불안정하여 다행 서버에 연결할 수 없어요 😢
32 | 현재 다행 사용자가 많아 일시적 오류가 발생했어요 😢\n문제가 지속되면 고객센터로 문의해 주세요.
33 |
34 | 위치 조회중…
35 | 다시 시도
36 | 장소 검색
37 | 나에게 맞는\n최고의 여행지를 찾아보세요!
38 | 내 일정
39 | 일정 생성
40 | 공유
41 | 수정
42 | 삭제
43 | 제목:
44 | 테마:
45 | 공통주소:
46 | 총 여행기간:
47 | 총 금액:
48 | 완료
49 |
50 |
51 | - 펜션
52 | - 캠핑
53 | - 스포츠
54 | - 힐링
55 | - 바다
56 | - 산
57 | - 음식
58 | - 명소
59 |
60 |
61 |
62 | - 항공
63 | - 배
64 | - 기차
65 | - 차
66 | - 대중교통
67 | - 도보
68 |
69 |
70 |
71 | - 모텔
72 | - 호텔
73 | - 리조트
74 | - 펜션
75 | - 게스트하우스
76 | - 한옥
77 |
78 |
79 |
--------------------------------------------------------------------------------
/presentation/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
18 |
19 |
24 |
25 |
34 |
35 |
40 |
41 |
46 |
47 |
52 |
53 |
57 |
58 |
62 |
--------------------------------------------------------------------------------
/secrets.tar.gpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dahaeng/dahaeng-android/8c61b8b5ae5f82dfde97f60795fc65b9abb1aceb/secrets.tar.gpg
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
2 | rootProject.name = "dahaeng-android"
3 | include(
4 | ":data",
5 | ":domain",
6 | ":presentation"
7 | )
8 |
--------------------------------------------------------------------------------