diff --git a/.editorconfig b/.editorconfig
index 1c514dae..5969a198 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,5 +1,5 @@
[*]
-max_line_length = 140
+max_line_length = off
[*.{kt, kts}]
disabled_rules = import-ordering, no-wildcard-imports
\ No newline at end of file
diff --git a/.github/workflows/pr_builder.yml b/.github/workflows/pr_builder.yml
index 6b446544..7b9fabf8 100644
--- a/.github/workflows/pr_builder.yml
+++ b/.github/workflows/pr_builder.yml
@@ -43,6 +43,36 @@ jobs:
- name: Touch local properties
run: touch local.properties
+ - name: Access KAKAO_NATIVE_KEY
+ env:
+ KAKAO_NATIVE_KEY: ${{ secrets.KAKAO_NATIVE_KEY }}
+ run: echo "KAKAO_NATIVE_KEY=\"$KAKAO_NATIVE_KEY\"" >> local.properties
+
+ - name: Access NAVER_CLIENT_ID
+ env:
+ NAVER_CLIENT_ID: ${{ secrets.NAVER_CLIENT_ID }}
+ run: echo "NAVER_CLIENT_ID=\"$NAVER_CLIENT_ID\"" >> local.properties
+
+ - name: Access NAVER_CLIENT_SECRETE
+ env:
+ NAVER_CLIENT_SECRETE: ${{ secrets.NAVER_CLIENT_SECRETE }}
+ run: echo "NAVER_CLIENT_SECRETE=\"$NAVER_CLIENT_SECRETE\"" >> local.properties
+
+ - name: Access KGE_BASE_URL
+ env:
+ HFM_BASE_URL: ${{ secrets.KGE_BASE_URL }}
+ run: echo "KGE_BASE_URL=\"$KGE_BASE_URL\"" >> local.properties
+
+ - name: Access MIXPANEL_PROD_TOKEN
+ env:
+ HFM_BASE_URL: ${{ secrets.MIXPANEL_PROD_TOKEN }}
+ run: echo "MIXPANEL_PROD_TOKEN=\"$MIXPANEL_PROD_TOKEN\"" >> local.properties
+
+ - name: Access MIXPANEL_DEV_TOKEN
+ env:
+ HFM_BASE_URL: ${{ secrets.MIXPANEL_DEV_TOKEN }}
+ run: echo "MIXPANEL_DEV_TOKEN=\"$MIXPANEL_DEV_TOKEN\"" >> local.properties
+
- name: Lint Check
run: ./gradlew ktlintCheck
diff --git a/README.md b/README.md
index e95550d9..356e3398 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,37 @@
# *๐ย Keep Go Eat - AOS ๐*
+
+
IN SOPT 31st APPJAM ํต๊ณ ์ Android ํ ๋ ํฌ์
๋๋ค.
## ๐ฅย *****Project*****
-
**ํต๊ณ ์(Keep-Go-Eat)**
-๊ณ์ ๋จน์ด๋ ๊ด์ฐฎ์.
-์คํธ๋ ์ค ๋ฐ์ง ์๊ณ ์ค์ค๋ก ์กฐ์ ํ๋ ๋๋ง์ ์์ต๊ด์ ์ฐพ์๊ฐ๋ ๊ธธ, ํต๊ณ ์
+
+
+
+์ข์ ์์์ ๋ ๋จน๊ณ , ๋์ ์์์ ๋ ๋จน๋ ๋ ์ ๋๋ ค๊ฐ๋๋ก ๋๋
+์ฆ๊ฑฐ์ด ์์ต๊ด ๊ธฐ๋ก ์๋น์ค, ํต๊ณ ์
+
+
+
+## ๐ท *****Screen*****
+| | | | |
+| :---: | :---: | :---: |:------------------------------------------------------------------------------------------------------------------------------:|
+|`LoginView`|`HomeView`|`HomeView`| `GoalDetailView` |
+| | | |
+|`GoalDetailView`|`GoalSettingView`|`MyPageView`| |
## ๐ *****Contributors*****
-| [@YuBeen-Park](https://github.com/YuBeen-Park) | [@Dani43](https://github.com/Dan2dani) | [@youngjinc](https://github.com/youngjinc) |
-| :---: | :---: | :---: |
-||||
-|`HomeView`|`LoginView`, `OnBoardingView`|`GoalSettingView`, `GoalDetailView`|
+| [@YuBeen-Park](https://github.com/YuBeen-Park) | [@Dani43](https://github.com/Dan2dani) | [@youngjinc](https://github.com/youngjinc) |
+|:------------------------------------------------------------------------------------------------------------------------------:| :---: | :---: |
+| |||
+| `HomeView`, `MyPageView` |`LoginView`, `OnBoardingView`|`GoalSettingView`, `GoalDetailView`|
@@ -29,7 +42,7 @@ IN SOPT 31st APPJAM ํต๊ณ ์ Android ํ ๋ ํฌ์
๋๋ค.
| Jetpack Components | encryptedsharedpreferences, LiveData, Lifecycle, ViewModel, DataBinding |
| Dependency Injection | Hilt |
| Network | Retrofit, OkHttp |
-| Asynchronous Processing | Coroutine |
+| Asynchronous Processing | Coroutine(+ Flow) |
| Third Party Library | Coil, Social Login, Firebase, Lottie, Timber, kotlinSerialization |
| Strategy | Git Flow |
| CI | GitHub Action(KtLint, Complie Check) |
@@ -78,4 +91,4 @@ IN SOPT 31st APPJAM ํต๊ณ ์ Android ํ ๋ ํฌ์
๋๋ค.
โฃ ๐ util
โ โฃ ๐ binding
โ โฃ ๐ extension
-```
\ No newline at end of file
+```
diff --git a/app/build.gradle b/app/build.gradle
index 365dd5fa..3d7c331a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -21,16 +21,28 @@ android {
applicationId "org.keepgoeat"
minSdk 28
targetSdk 33
- versionCode 1
- versionName "1.0"
+ versionCode 16
+ versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ buildConfigField "String", "KGE_BASE_URL", properties["KGE_BASE_URL"]
+ buildConfigField "String", "KAKAO_NATIVE_KEY", properties["KAKAO_NATIVE_KEY"]
+ buildConfigField "String", "NAVER_CLIENT_ID", properties["NAVER_CLIENT_ID"]
+ buildConfigField "String", "NAVER_CLIENT_SECRETE", properties["NAVER_CLIENT_SECRETE"]
}
buildTypes {
- release {
+ debug {
+ manifestPlaceholders = [KAKAO_NATIVE_KEY: properties["KAKAO_NATIVE_KEY"]]
minifyEnabled false
+ buildConfigField "String", "MIXPANEL_PROJECT_TOKEN", properties["MIXPANEL_DEV_TOKEN"]
+ }
+ release {
+ manifestPlaceholders = [KAKAO_NATIVE_KEY: properties["KAKAO_NATIVE_KEY"]]
+ minifyEnabled true
+ shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ buildConfigField "String", "MIXPANEL_PROJECT_TOKEN", properties["MIXPANEL_PROD_TOKEN"]
}
}
compileOptions {
@@ -52,6 +64,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.recyclerview:recyclerview:1.2.0-rc01'
// Ktx
implementation 'androidx.activity:activity-ktx:1.6.0'
@@ -63,6 +76,7 @@ dependencies {
implementation "com.google.dagger:hilt-android:$hilt_version"
implementation 'androidx.hilt:hilt-navigation-fragment:1.0.0'
kapt "com.google.dagger:hilt-compiler:$hilt_version"
+ kapt "com.google.dagger:dagger-compiler:$hilt_version"
// Coil
implementation 'io.coil-kt:coil:2.2.2'
@@ -77,15 +91,37 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1'
+ implementation 'com.google.code.gson:gson:2.10'
// Firebase
implementation platform('com.google.firebase:firebase-bom:31.1.1')
implementation 'com.google.firebase:firebase-crashlytics-ktx'
- implementation 'com.google.firebase:firebase-analytics-ktx'
+
+ // Mixpanel
+ implementation 'com.mixpanel.android:mixpanel-android:7.+'
+
+ // KakaoSignIn
+ implementation "com.kakao.sdk:v2-user:2.12.0"
+
+ // NaverSignIn
+ implementation 'com.navercorp.nid:oauth-jdk8:5.3.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
+
+ // ViewPager2
+ implementation 'androidx.viewpager2:viewpager2:1.0.0'
+
+ // Splashscreen
+ implementation 'androidx.core:core-splashscreen:1.0.0'
+
+ // Lottie
+ implementation 'com.airbnb.android:lottie:5.2.0'
+
+ // In-App Review
+ implementation 'com.google.android.play:review:2.0.1'
+ implementation 'com.google.android.play:review-ktx:2.0.1'
}
ktlint {
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 481bb434..8ac59583 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -18,4 +18,12 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
-#-renamesourcefileattribute SourceFile
\ No newline at end of file
+#-renamesourcefileattribute SourceFile
+
+-keep class com.kakao.sdk.**.model.* { ; }
+-keep public class com.navercorp.nid.** { public *; }
+-keep class * extends com.google.gson.TypeAdapter
+
+-keepnames class * extends android.os.Parcelable
+-keepnames class * extends java.io.Serializable
+-keep class org.keepgoeat.data.model.** { *; }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dcd7f02a..e11ca310 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,31 +3,102 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
+ android:name=".presentation.SplashActivity"
+ android:exported="true"
+ android:screenOrientation="portrait"
+ android:theme="@style/Theme.KeepGoEat.Splash"
+ tools:ignore="LockedOrientationActivity">
-
-
+ android:name=".presentation.home.HomeActivity"
+ android:exported="true"
+ android:screenOrientation="portrait"
+ tools:ignore="LockedOrientationActivity" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/ic_keepgoeat-playstore.png b/app/src/main/ic_keepgoeat-playstore.png
new file mode 100644
index 00000000..0c5e588e
Binary files /dev/null and b/app/src/main/ic_keepgoeat-playstore.png differ
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 00000000..ef839318
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/java/org/keepgoeat/App.kt b/app/src/main/java/org/keepgoeat/App.kt
index 5bcab8fc..1086d8f7 100644
--- a/app/src/main/java/org/keepgoeat/App.kt
+++ b/app/src/main/java/org/keepgoeat/App.kt
@@ -1,7 +1,10 @@
package org.keepgoeat
import android.app.Application
+import androidx.appcompat.app.AppCompatDelegate
+import com.kakao.sdk.common.KakaoSdk
import dagger.hilt.android.HiltAndroidApp
+import org.keepgoeat.BuildConfig.KAKAO_NATIVE_KEY
import org.keepgoeat.util.KGEDebugTree
import timber.log.Timber
@@ -9,6 +12,8 @@ import timber.log.Timber
class App : Application() {
override fun onCreate() {
super.onCreate()
+ KakaoSdk.init(this, KAKAO_NATIVE_KEY)
if (BuildConfig.DEBUG) Timber.plant(KGEDebugTree())
+ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}
diff --git a/app/src/main/java/org/keepgoeat/data/ApiResponse.kt b/app/src/main/java/org/keepgoeat/data/ApiResponse.kt
deleted file mode 100644
index a96b8f2f..00000000
--- a/app/src/main/java/org/keepgoeat/data/ApiResponse.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.keepgoeat.data
-
-sealed class ApiResponse(val data: T?) { // TODO ์์
- data class Idle(val datas: T?) : ApiResponse(null)
- data class Loading(val datas: T?) : ApiResponse(datas)
- data class Success(val datas: T) : ApiResponse(datas)
- data class Failure(val throwable: Throwable?) : ApiResponse(null)
-}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/local/KGEDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/local/KGEDataSource.kt
index 2f9410b5..8b055882 100644
--- a/app/src/main/java/org/keepgoeat/data/datasource/local/KGEDataSource.kt
+++ b/app/src/main/java/org/keepgoeat/data/datasource/local/KGEDataSource.kt
@@ -1,6 +1,93 @@
package org.keepgoeat.data.datasource.local
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.core.content.edit
+import androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
+import dagger.hilt.android.qualifiers.ApplicationContext
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.presentation.type.LoginPlatformType
+import org.keepgoeat.util.safeValueOf
+import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class KGEDataSource
+class KGEDataSource @Inject constructor(@ApplicationContext context: Context) {
+
+ private val masterKey = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+
+ private val dataStore: SharedPreferences =
+ if (BuildConfig.DEBUG) context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
+ else EncryptedSharedPreferences.create(
+ context,
+ FILE_NAME,
+ masterKey,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ )
+
+ var accessToken: String
+ set(value) = dataStore.edit { putString(ACCESS_TOKEN, value) }
+ get() = dataStore.getString(
+ ACCESS_TOKEN,
+ ""
+ ) ?: ""
+
+ var refreshToken: String
+ set(value) = dataStore.edit { putString(REFRESH_TOKEN, value) }
+ get() = dataStore.getString(
+ REFRESH_TOKEN,
+ ""
+ ) ?: ""
+
+ var isLogin: Boolean
+ set(value) = dataStore.edit { putBoolean(IS_LOGIN, value) }
+ get() = dataStore.getBoolean(IS_LOGIN, false)
+
+ var isClickedOnboardingButton: Boolean
+ set(value) = dataStore.edit { putBoolean(IS_CLICKED_ONBOARDING_BUTTON, value) }
+ get() = dataStore.getBoolean(IS_CLICKED_ONBOARDING_BUTTON, false)
+
+ var loginPlatform: LoginPlatformType
+ set(value) = dataStore.edit { putString(LOGIN_PLATFORM, value.name) }
+ get() = safeValueOf(dataStore.getString(LOGIN_PLATFORM, ""))
+ ?: LoginPlatformType.NONE
+
+ var userEmail: String
+ set(value) = dataStore.edit { putString(USER_EMAIL, value) }
+ get() = dataStore.getString(USER_EMAIL, "") ?: ""
+
+ var userName: String
+ set(value) = dataStore.edit { putString(USER_NAME, value) }
+ get() = dataStore.getString(USER_NAME, "") ?: ""
+
+ /** ๋ก๊ทธ์์ ๋ฐ ํ์ ํํด ์ ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ํจ์ (๋จ, ๋ก๊ทธ์์์ ๊ฒฝ์ฐ IS_CLICKED_ONBOARDING_BUTTON์ ์ ์ธํ๊ณ ์ญ์ ํ๋ค. ์ฌ๋ก๊ทธ์ธ ์ ์จ๋ณด๋ฉ ๋์ฐ๊ธฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํจ)*/
+ fun clear(isWithdrawal: Boolean = false) {
+ dataStore.edit {
+ if (isWithdrawal) {
+ clear()
+ } else {
+ remove(ACCESS_TOKEN)
+ remove(REFRESH_TOKEN)
+ remove(IS_LOGIN)
+ remove(LOGIN_PLATFORM)
+ remove(USER_NAME)
+ remove(USER_EMAIL)
+ }
+ }
+ }
+
+ companion object {
+ const val FILE_NAME = "signSharedPreferences"
+ const val ACCESS_TOKEN = "accessToken"
+ const val REFRESH_TOKEN = "refreshToken"
+ const val IS_LOGIN = "isLogin"
+ const val IS_CLICKED_ONBOARDING_BUTTON = "isClickedOnboardingButton"
+ const val LOGIN_PLATFORM = "loginPlatform"
+ const val USER_EMAIL = "userEmail"
+ const val USER_NAME = "userName"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/remote/AuthDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/remote/AuthDataSource.kt
new file mode 100644
index 00000000..39a66d25
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/datasource/remote/AuthDataSource.kt
@@ -0,0 +1,21 @@
+package org.keepgoeat.data.datasource.remote
+
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.data.model.request.RequestAuth
+import org.keepgoeat.data.model.response.ResponseAuth
+import org.keepgoeat.data.model.response.ResponseRefresh
+import org.keepgoeat.data.model.response.ResponseWithdraw
+import org.keepgoeat.data.service.AuthService
+import javax.inject.Inject
+
+class AuthDataSource @Inject constructor(
+ private val authService: AuthService,
+ private val kgeDataSource: KGEDataSource,
+) {
+ suspend fun login(requestAuth: RequestAuth): ResponseAuth = authService.login(requestAuth)
+
+ suspend fun refresh(): ResponseRefresh = authService.refresh()
+
+ suspend fun deleteAccount(): ResponseWithdraw =
+ authService.deleteAccount(kgeDataSource.loginPlatform.name)
+}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/remote/DummyDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/remote/DummyDataSource.kt
deleted file mode 100644
index 2eb4c1d5..00000000
--- a/app/src/main/java/org/keepgoeat/data/datasource/remote/DummyDataSource.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.keepgoeat.data.datasource.remote
-
-import org.keepgoeat.data.model.request.RequestData
-import org.keepgoeat.data.model.response.ResponseResult
-import org.keepgoeat.data.service.DummyService
-import javax.inject.Inject
-
-class DummyDataSource @Inject constructor(
- private val dummyService: DummyService,
-) {
- suspend fun uploadDummy(signInRequest: RequestData): ResponseResult {
- // dummyService.uploadDummy(signInRequest) // TODO api ์์ฒญํ๊ธฐ
- return ResponseResult(
- 1,
- "success",
- ResponseResult.ResponseData(1, "keepgoeat", "keepgoeat@gmamil.com")
- )
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/remote/GoalDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/remote/GoalDataSource.kt
new file mode 100644
index 00000000..996afbf3
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/datasource/remote/GoalDataSource.kt
@@ -0,0 +1,40 @@
+package org.keepgoeat.data.datasource.remote
+
+import org.keepgoeat.data.model.request.RequestGoalAchievement
+import org.keepgoeat.data.model.request.RequestGoalContent
+import org.keepgoeat.data.model.request.RequestEditedGoalContent
+import org.keepgoeat.data.model.response.*
+import org.keepgoeat.data.service.GoalService
+import javax.inject.Inject
+
+class GoalDataSource @Inject constructor(
+ private val goalService: GoalService,
+) {
+ suspend fun fetchHomeContent(): ResponseHomeContent =
+ goalService.fetchHomeContent()
+
+ suspend fun fetchGoalDetail(id: Int): ResponseGoalDetail = goalService.fetchGoalDetail(id)
+
+ suspend fun fetchArchivedGoal(sortType: String): ResponseArchivedGoal =
+ goalService.fetchArchivedGoal(sortType)
+
+ suspend fun uploadGoalContent(content: RequestGoalContent): ResponseGoalContent =
+ goalService.uploadGoalContent(content)
+
+ suspend fun editGoalContent(
+ id: Int,
+ content: RequestEditedGoalContent,
+ ): ResponseGoalContent = goalService.editGoalContent(id, content)
+
+ suspend fun keepGoal(id: Int): ResponseGoalKeep = goalService.keepGoal(id)
+
+ suspend fun achieveGoal(
+ id: Int,
+ requestGoalAchievement: RequestGoalAchievement
+ ): ResponseGoalAchievement =
+ goalService.achieveGoal(id, requestGoalAchievement)
+
+ suspend fun deleteGoal(
+ id: Int
+ ): ResponseGoalDeleted = goalService.deleteGoal(id)
+}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/remote/UserDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/remote/UserDataSource.kt
new file mode 100644
index 00000000..e4828382
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/datasource/remote/UserDataSource.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.data.datasource.remote
+
+import org.keepgoeat.data.model.response.ResponseUserInfo
+import org.keepgoeat.data.service.UserService
+import javax.inject.Inject
+
+class UserDataSource @Inject constructor(
+ private val userService: UserService,
+) {
+ suspend fun fetchUserInfo(): ResponseUserInfo =
+ userService.fetchUserInfo()
+}
diff --git a/app/src/main/java/org/keepgoeat/data/datasource/remote/VersionDataSource.kt b/app/src/main/java/org/keepgoeat/data/datasource/remote/VersionDataSource.kt
new file mode 100644
index 00000000..a7365d1f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/datasource/remote/VersionDataSource.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.data.datasource.remote
+
+import org.keepgoeat.data.model.response.ResponseVersion
+import org.keepgoeat.data.service.VersionService
+import javax.inject.Inject
+
+class VersionDataSource @Inject constructor(
+ private val versionService: VersionService,
+) {
+ suspend fun getForcedUpdateVersion(clientType: String): ResponseVersion =
+ versionService.getForcedUpdateVersion(clientType)
+}
diff --git a/app/src/main/java/org/keepgoeat/data/interceptor/AuthInterceptor.kt b/app/src/main/java/org/keepgoeat/data/interceptor/AuthInterceptor.kt
new file mode 100644
index 00000000..df80c936
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/interceptor/AuthInterceptor.kt
@@ -0,0 +1,79 @@
+package org.keepgoeat.data.interceptor
+
+import android.app.Application
+import android.content.Intent
+import com.google.gson.Gson
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.R
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.data.model.response.ResponseRefresh
+import org.keepgoeat.util.extension.showToast
+import javax.inject.Inject
+
+class AuthInterceptor @Inject constructor(
+ private val localStorage: KGEDataSource,
+ private val gson: Gson,
+ private val context: Application,
+) : Interceptor {
+
+ override fun intercept(chain: Interceptor.Chain): Response {
+ val originalRequest = chain.request()
+ val authRequest = originalRequest.newAuthBuilder().build()
+ val response = chain.proceed(authRequest)
+
+ when (response.code) {
+ 401 -> {
+ val refreshTokenRequest = originalRequest.newBuilder().get()
+ .url("${BuildConfig.KGE_BASE_URL}auth/refresh")
+ .addHeader(ACCESS_TOKEN, localStorage.accessToken)
+ .addHeader(REFRESH_TOKEN, localStorage.refreshToken)
+ .build()
+ val refreshTokenResponse = chain.proceed(refreshTokenRequest)
+
+ if (refreshTokenResponse.isSuccessful) {
+ val responseRefresh = gson.fromJson(
+ refreshTokenResponse.body?.string(),
+ ResponseRefresh::class.java
+ )
+ with(localStorage) {
+ accessToken = responseRefresh.data.accessToken
+ refreshToken = responseRefresh.data.refreshToken
+ }
+ val newRequest = originalRequest.newAuthBuilder().build()
+ return chain.proceed(newRequest)
+ } else {
+ with(context) {
+ CoroutineScope(Dispatchers.Main).launch {
+ startActivity(
+ Intent.makeRestartActivityTask(
+ packageManager.getLaunchIntentForPackage(packageName)?.component
+ )
+ )
+ showToast(getString(R.string.auto_login_failure))
+ localStorage.clear()
+ cancel()
+ }
+ }
+ }
+ }
+ }
+ return response
+ }
+
+ private fun Request.newAuthBuilder() =
+ this.newBuilder()
+ .addHeader(ACCESS_TOKEN, localStorage.accessToken)
+ .addHeader(REFRESH_TOKEN, localStorage.refreshToken)
+
+ companion object {
+ private const val ACCESS_TOKEN = "accesstoken"
+ private const val REFRESH_TOKEN = "refreshtoken"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/request/RequestAuth.kt b/app/src/main/java/org/keepgoeat/data/model/request/RequestAuth.kt
new file mode 100644
index 00000000..47936aac
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/request/RequestAuth.kt
@@ -0,0 +1,9 @@
+package org.keepgoeat.data.model.request
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RequestAuth(
+ val platformAccessToken: String,
+ val platform: String,
+)
diff --git a/app/src/main/java/org/keepgoeat/data/model/request/RequestEditedGoalContent.kt b/app/src/main/java/org/keepgoeat/data/model/request/RequestEditedGoalContent.kt
new file mode 100644
index 00000000..b8bb82a5
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/request/RequestEditedGoalContent.kt
@@ -0,0 +1,9 @@
+package org.keepgoeat.data.model.request
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RequestEditedGoalContent(
+ val food: String,
+ val criterion: String
+)
diff --git a/app/src/main/java/org/keepgoeat/data/model/request/RequestData.kt b/app/src/main/java/org/keepgoeat/data/model/request/RequestGoalAchievement.kt
similarity index 59%
rename from app/src/main/java/org/keepgoeat/data/model/request/RequestData.kt
rename to app/src/main/java/org/keepgoeat/data/model/request/RequestGoalAchievement.kt
index 10f5cc49..74c704a5 100644
--- a/app/src/main/java/org/keepgoeat/data/model/request/RequestData.kt
+++ b/app/src/main/java/org/keepgoeat/data/model/request/RequestGoalAchievement.kt
@@ -3,7 +3,6 @@ package org.keepgoeat.data.model.request
import kotlinx.serialization.Serializable
@Serializable
-data class RequestData(
- val name: String,
- val email: String,
+data class RequestGoalAchievement(
+ val isAchieved: Boolean
)
diff --git a/app/src/main/java/org/keepgoeat/data/model/request/RequestGoalContent.kt b/app/src/main/java/org/keepgoeat/data/model/request/RequestGoalContent.kt
new file mode 100644
index 00000000..c6a8f44b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/request/RequestGoalContent.kt
@@ -0,0 +1,10 @@
+package org.keepgoeat.data.model.request
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RequestGoalContent(
+ val food: String,
+ val criterion: String,
+ val isMore: Boolean,
+)
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseArchivedGoal.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseArchivedGoal.kt
new file mode 100644
index 00000000..7f40048b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseArchivedGoal.kt
@@ -0,0 +1,44 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+import org.keepgoeat.domain.model.ArchivedGoal
+import org.keepgoeat.presentation.type.EatingType
+
+@Serializable
+data class ResponseArchivedGoal(
+ val status: Int,
+ val success: Boolean,
+ val message: String,
+ val data: ResponseArchivedGoalData,
+) {
+ @Serializable
+ data class ResponseArchivedGoalData(
+ val goals: List,
+ val goalCount: Int,
+ ) {
+ @Serializable
+ data class GoalInfo(
+ val goalId: Int,
+ val food: String,
+ val criterion: String,
+ val isMore: Boolean,
+ val isOngoing: Boolean,
+ val writerId: Int,
+ val totalCount: Int,
+ val startedAt: String,
+ val keptAt: String?,
+ val isAchieved: Boolean,
+ )
+
+ fun toMyGoal() = goals.map { goal ->
+ ArchivedGoal(
+ goal.goalId,
+ goal.food,
+ if (goal.isMore) EatingType.MORE else EatingType.LESS,
+ goal.startedAt,
+ goal.keptAt,
+ goal.totalCount
+ )
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseAuth.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseAuth.kt
new file mode 100644
index 00000000..6eee21ac
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseAuth.kt
@@ -0,0 +1,29 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+import org.keepgoeat.domain.model.AuthInfo
+import org.keepgoeat.domain.type.SignType.SIGN_IN
+import org.keepgoeat.domain.type.SignType.SIGN_UP
+
+@Serializable
+data class ResponseAuth(
+ val data: ResponseAuthData?,
+ val message: String,
+ val status: Int,
+ val success: Boolean,
+) {
+ @Serializable
+ data class ResponseAuthData(
+ val type: String,
+ val email: String,
+ val accessToken: String,
+ val refreshToken: String,
+ ) {
+ fun toAuthInfo() = AuthInfo(
+ if (type == SIGN_UP.typeStr) SIGN_UP else SIGN_IN,
+ email,
+ accessToken,
+ refreshToken
+ )
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalAchievement.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalAchievement.kt
new file mode 100644
index 00000000..ff8aeced
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalAchievement.kt
@@ -0,0 +1,18 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseGoalAchievement(
+ val data: ResponseGoalAchievementData,
+ val message: String,
+ val status: Int,
+ val success: Boolean
+) {
+ @Serializable
+ data class ResponseGoalAchievementData(
+ val goalId: Int,
+ val thisMonthCount: Int,
+ val updatedIsAchieved: Boolean
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalContent.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalContent.kt
new file mode 100644
index 00000000..d3ee7645
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalContent.kt
@@ -0,0 +1,18 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseGoalContent(
+ val status: Int,
+ val success: Boolean,
+ val message: String,
+ val data: ResponseGoalContentData,
+) {
+ @Serializable
+ data class ResponseGoalContentData(
+ @SerialName("goalId")
+ val id: Int,
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDeleted.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDeleted.kt
new file mode 100644
index 00000000..7b1359b1
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDeleted.kt
@@ -0,0 +1,16 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseGoalDeleted(
+ val data: ResponseGoalDeletedData,
+ val message: String,
+ val status: Int,
+ val success: Boolean
+) {
+ @Serializable
+ data class ResponseGoalDeletedData(
+ val goalId: Int
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDetail.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDetail.kt
new file mode 100644
index 00000000..89ae7c92
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalDetail.kt
@@ -0,0 +1,36 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import org.keepgoeat.domain.model.GoalDetail
+import org.keepgoeat.presentation.type.EatingType
+
+@Serializable
+data class ResponseGoalDetail(
+ val status: Int,
+ val success: Boolean,
+ val message: String,
+ val data: ResponseGoalDetailData,
+) {
+ @Serializable
+ data class ResponseGoalDetailData(
+ @SerialName("goalId")
+ val id: Int,
+ val isMore: Boolean,
+ val thisMonthCount: Int,
+ val lastMonthCount: Int,
+ val blankBoxCount: Int,
+ val emptyBoxCount: Int,
+ val food: String,
+ val criterion: String
+ ) {
+ fun toGoalDetail() = GoalDetail(
+ id = id,
+ eatingType = if (isMore) EatingType.MORE else EatingType.LESS,
+ thisMonthCount = thisMonthCount,
+ lastMonthCount = lastMonthCount,
+ food = food,
+ criterion = criterion
+ )
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalKeep.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalKeep.kt
new file mode 100644
index 00000000..3d9dddea
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseGoalKeep.kt
@@ -0,0 +1,16 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseGoalKeep(
+ val data: ResponseGoalKeepData,
+ val message: String,
+ val status: Int,
+ val success: Boolean
+) {
+ @Serializable
+ data class ResponseGoalKeepData(
+ val goalId: Int
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseHomeContent.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseHomeContent.kt
new file mode 100644
index 00000000..ba63f3dd
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseHomeContent.kt
@@ -0,0 +1,52 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+import org.keepgoeat.domain.model.HomeContent
+import org.keepgoeat.domain.model.HomeGoal
+import org.keepgoeat.presentation.type.HomeGoalViewType
+
+@Serializable
+data class ResponseHomeContent(
+ val data: HomeData,
+ val message: String,
+ val status: Int,
+ val success: Boolean,
+) {
+ @Serializable
+ data class HomeData(
+ val cheeringMessage: String,
+ val daytime: Int,
+ val goalCount: Int,
+ val goals: List,
+ ) {
+ @Serializable
+ data class Goal(
+ val food: String,
+ val criterion: String,
+ val goalId: Int,
+ val isAchieved: Boolean,
+ val isMore: Boolean,
+ val isOngoing: Boolean,
+ val keptAt: String,
+ val startedAt: String,
+ val thisMonthCount: Int,
+ val totalCount: Int,
+ val writerId: Int,
+ )
+
+ fun toHomeContent() = HomeContent(
+ cheeringMessage.replace("\\n", "\n"),
+ goals.map { goal ->
+ HomeGoal(
+ goal.goalId,
+ goal.food,
+ goal.criterion,
+ goal.isMore,
+ goal.isAchieved,
+ goal.thisMonthCount,
+ HomeGoalViewType.MY_GOAL_TYPE
+ )
+ }
+ )
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseRefresh.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseRefresh.kt
new file mode 100644
index 00000000..4fd4f317
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseRefresh.kt
@@ -0,0 +1,17 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseRefresh(
+ val status: Int,
+ val success: Boolean,
+ val message: String,
+ val data: ResponseToken,
+) {
+ @Serializable
+ data class ResponseToken(
+ val accessToken: String,
+ val refreshToken: String
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseResult.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseResult.kt
deleted file mode 100644
index 03764215..00000000
--- a/app/src/main/java/org/keepgoeat/data/model/response/ResponseResult.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.keepgoeat.data.model.response
-
-import kotlinx.serialization.Serializable
-import org.keepgoeat.domain.model.DummyData
-
-@Serializable
-data class ResponseResult(
- val status: Int,
- val message: String,
- val data: ResponseData,
-) {
- @Serializable
- data class ResponseData( // TODO ResponseUser๊ฐ ์ค๋ณต์ผ๋ก ์ฌ์ฉ๋๋ค๋ฉด ํ์ผ ๋ถ๋ฆฌํ๊ธฐ
- val id: Int,
- val name: String,
- val email: String,
- ) {
- fun toDummyData() = DummyData(
- id = id.toString(),
- email = email,
- name = name
- )
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseUserInfo.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseUserInfo.kt
new file mode 100644
index 00000000..682969e3
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseUserInfo.kt
@@ -0,0 +1,21 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+import org.keepgoeat.domain.model.UserInfo
+
+@Serializable
+data class ResponseUserInfo(
+ val data: ResponseUserData?,
+ val message: String,
+ val status: Int,
+ val success: Boolean,
+) {
+ @Serializable
+ data class ResponseUserData(
+ val name: String,
+ val email: String,
+ val keptGoalsCount: Int,
+ ) {
+ fun toUserInfo() = UserInfo(name, email, keptGoalsCount)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseVersion.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseVersion.kt
new file mode 100644
index 00000000..7d8ffb93
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseVersion.kt
@@ -0,0 +1,16 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseVersion(
+ val status: Int,
+ val success: Boolean,
+ val message: String,
+ val data: VersionData
+) {
+ @Serializable
+ data class VersionData(
+ val version: String
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/data/model/response/ResponseWithdraw.kt b/app/src/main/java/org/keepgoeat/data/model/response/ResponseWithdraw.kt
new file mode 100644
index 00000000..34186159
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/model/response/ResponseWithdraw.kt
@@ -0,0 +1,10 @@
+package org.keepgoeat.data.model.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ResponseWithdraw(
+ val message: String,
+ val status: Int,
+ val success: Boolean,
+)
diff --git a/app/src/main/java/org/keepgoeat/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/org/keepgoeat/data/repository/AuthRepositoryImpl.kt
new file mode 100644
index 00000000..5abd041f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/repository/AuthRepositoryImpl.kt
@@ -0,0 +1,50 @@
+package org.keepgoeat.data.repository
+
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.data.datasource.remote.AuthDataSource
+import org.keepgoeat.data.model.request.RequestAuth
+import org.keepgoeat.data.model.response.ResponseRefresh
+import org.keepgoeat.data.model.response.ResponseWithdraw
+import org.keepgoeat.domain.model.AuthInfo
+import org.keepgoeat.domain.repository.AuthRepository
+import org.keepgoeat.domain.type.SignType
+import timber.log.Timber
+import javax.inject.Inject
+
+class AuthRepositoryImpl @Inject constructor(
+ private val authDataSource: AuthDataSource,
+ private val localStorage: KGEDataSource,
+) : AuthRepository {
+ override suspend fun login(requestAuth: RequestAuth): Result =
+ runCatching {
+ authDataSource.login(requestAuth).data?.toAuthInfo()
+ }.onSuccess {
+ with(localStorage) {
+ isLogin = true
+ it?.let {
+ accessToken = it.accessToken
+ refreshToken = it.refreshToken
+
+ if (it.signType == SignType.SIGN_IN)
+ isClickedOnboardingButton = true
+ }
+ }
+ }.onFailure {
+ Timber.e(it.message)
+ }
+
+ override suspend fun deleteAccount(): Result =
+ runCatching {
+ authDataSource.deleteAccount()
+ }.onSuccess {
+ Timber.d("ํ์ ํํด ์ฑ๊ณต")
+ localStorage.clear(true)
+ }.onFailure {
+ Timber.e(it.message)
+ }
+
+ override suspend fun refresh(): Result =
+ runCatching {
+ authDataSource.refresh().data
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/repository/DummyRepositoryImpl.kt b/app/src/main/java/org/keepgoeat/data/repository/DummyRepositoryImpl.kt
deleted file mode 100644
index 3cb6bca3..00000000
--- a/app/src/main/java/org/keepgoeat/data/repository/DummyRepositoryImpl.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.keepgoeat.data.repository
-
-import org.keepgoeat.data.datasource.remote.DummyDataSource
-import org.keepgoeat.data.model.request.RequestData
-import org.keepgoeat.domain.repository.DummyRepository
-import javax.inject.Inject
-
-class DummyRepositoryImpl @Inject constructor(
- private val dummyDataSource: DummyDataSource,
-) : DummyRepository {
- override suspend fun uploadDummy(name: String, email: String) {
- dummyDataSource.uploadDummy(RequestData(name, email))
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/data/repository/GoalRepositoryImpl.kt b/app/src/main/java/org/keepgoeat/data/repository/GoalRepositoryImpl.kt
new file mode 100644
index 00000000..2d659384
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/repository/GoalRepositoryImpl.kt
@@ -0,0 +1,64 @@
+package org.keepgoeat.data.repository
+
+import org.keepgoeat.data.datasource.remote.GoalDataSource
+import org.keepgoeat.data.model.request.RequestGoalAchievement
+import org.keepgoeat.data.model.request.RequestGoalContent
+import org.keepgoeat.data.model.request.RequestEditedGoalContent
+import org.keepgoeat.data.model.response.*
+import org.keepgoeat.domain.model.GoalDetail
+import org.keepgoeat.domain.model.ArchivedGoal
+import org.keepgoeat.domain.model.HomeContent
+import org.keepgoeat.domain.repository.GoalRepository
+import javax.inject.Inject
+
+class GoalRepositoryImpl @Inject constructor(
+ private val goalDataSource: GoalDataSource,
+) : GoalRepository {
+ override suspend fun fetchHomeContent(): Result = runCatching {
+ goalDataSource.fetchHomeContent().data.toHomeContent()
+ }
+
+ override suspend fun achieveGoal(
+ goalId: Int,
+ isAchieved: Boolean,
+ ): Result = runCatching {
+ goalDataSource.achieveGoal(goalId, RequestGoalAchievement(isAchieved)).data
+ }
+
+ override suspend fun uploadGoalContent(
+ food: String,
+ criterion: String,
+ isMore: Boolean,
+ ): Result =
+ runCatching {
+ goalDataSource.uploadGoalContent(RequestGoalContent(food, criterion, isMore)).data.id
+ }
+
+ override suspend fun editGoalContent(
+ id: Int,
+ food: String,
+ criterion: String
+ ): Result = runCatching {
+ goalDataSource.editGoalContent(id, RequestEditedGoalContent(food, criterion)).data.id
+ }
+
+ override suspend fun fetchGoalDetail(goalId: Int): Result =
+ runCatching {
+ goalDataSource.fetchGoalDetail(goalId).data.toGoalDetail()
+ }
+
+ override suspend fun fetchArchivedGoal(sortType: String): Result> =
+ runCatching {
+ goalDataSource.fetchArchivedGoal(sortType).data.toMyGoal()
+ }
+
+ override suspend fun keepGoal(id: Int): Result =
+ runCatching {
+ goalDataSource.keepGoal(id).data
+ }
+
+ override suspend fun deleteGoal(id: Int): Result =
+ runCatching {
+ goalDataSource.deleteGoal(id).data
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/repository/UserRepositoryImpl.kt b/app/src/main/java/org/keepgoeat/data/repository/UserRepositoryImpl.kt
new file mode 100644
index 00000000..16fa2259
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/repository/UserRepositoryImpl.kt
@@ -0,0 +1,15 @@
+package org.keepgoeat.data.repository
+
+import org.keepgoeat.data.datasource.remote.UserDataSource
+import org.keepgoeat.domain.model.UserInfo
+import org.keepgoeat.domain.repository.UserRepository
+import javax.inject.Inject
+
+class UserRepositoryImpl @Inject constructor(
+ private val userDataSource: UserDataSource,
+) : UserRepository {
+ override suspend fun fetchUserInfo(): Result =
+ runCatching {
+ userDataSource.fetchUserInfo().data?.toUserInfo()
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/repository/VersionRepositoryImpl.kt b/app/src/main/java/org/keepgoeat/data/repository/VersionRepositoryImpl.kt
new file mode 100644
index 00000000..4f816b5c
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/repository/VersionRepositoryImpl.kt
@@ -0,0 +1,15 @@
+package org.keepgoeat.data.repository
+
+import org.keepgoeat.data.datasource.remote.VersionDataSource
+import org.keepgoeat.data.model.response.ResponseVersion
+import org.keepgoeat.domain.repository.VersionRepository
+import javax.inject.Inject
+
+class VersionRepositoryImpl @Inject constructor(
+ private val versionDataSource: VersionDataSource
+) : VersionRepository {
+ override suspend fun getForcedUpdateVersion(clientType: String): Result =
+ runCatching {
+ versionDataSource.getForcedUpdateVersion(clientType).data
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/AuthService.kt b/app/src/main/java/org/keepgoeat/data/service/AuthService.kt
new file mode 100644
index 00000000..36da12f7
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/AuthService.kt
@@ -0,0 +1,21 @@
+package org.keepgoeat.data.service
+
+import org.keepgoeat.data.model.request.RequestAuth
+import org.keepgoeat.data.model.response.ResponseAuth
+import org.keepgoeat.data.model.response.ResponseRefresh
+import org.keepgoeat.data.model.response.ResponseWithdraw
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Query
+
+interface AuthService {
+ @POST("auth")
+ suspend fun login(@Body authInfo: RequestAuth): ResponseAuth
+
+ @GET("auth/refresh")
+ suspend fun refresh(): ResponseRefresh
+
+ @GET("auth/withdraw")
+ suspend fun deleteAccount(@Query("code") platform: String): ResponseWithdraw
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/DummyService.kt b/app/src/main/java/org/keepgoeat/data/service/DummyService.kt
deleted file mode 100644
index c5fa4d07..00000000
--- a/app/src/main/java/org/keepgoeat/data/service/DummyService.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keepgoeat.data.service
-
-import org.keepgoeat.data.model.request.RequestData
-import org.keepgoeat.data.model.response.ResponseResult
-import retrofit2.http.Body
-import retrofit2.http.POST
-
-interface DummyService {
- @POST("api/dummy")
- suspend fun uploadDummy(@Body request: RequestData): ResponseResult
-}
diff --git a/app/src/main/java/org/keepgoeat/data/service/GoalService.kt b/app/src/main/java/org/keepgoeat/data/service/GoalService.kt
new file mode 100644
index 00000000..4755896e
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/GoalService.kt
@@ -0,0 +1,43 @@
+package org.keepgoeat.data.service
+
+import org.keepgoeat.data.model.request.RequestGoalAchievement
+import org.keepgoeat.data.model.request.RequestGoalContent
+import org.keepgoeat.data.model.request.RequestEditedGoalContent
+import org.keepgoeat.data.model.response.*
+import retrofit2.http.*
+
+interface GoalService {
+ @GET("home")
+ suspend fun fetchHomeContent(): ResponseHomeContent
+
+ @POST("goal")
+ suspend fun uploadGoalContent(@Body goalContent: RequestGoalContent): ResponseGoalContent
+
+ @POST("goal/{goalId}")
+ suspend fun editGoalContent(
+ @Path("goalId") id: Int,
+ @Body goalContent: RequestEditedGoalContent
+ ): ResponseGoalContent
+
+ @GET("history/{goalId}")
+ suspend fun fetchGoalDetail(@Path("goalId") id: Int): ResponseGoalDetail
+
+ @GET("goal/kept")
+ suspend fun fetchArchivedGoal(
+ @Query("sort") sortType: String,
+ ): ResponseArchivedGoal
+
+ @POST("goal/keep/{goalId}")
+ suspend fun keepGoal(@Path("goalId") id: Int): ResponseGoalKeep
+
+ @POST("goal/achieve/{goalId}")
+ suspend fun achieveGoal(
+ @Path("goalId") id: Int,
+ @Body goalAchievement: RequestGoalAchievement
+ ): ResponseGoalAchievement
+
+ @DELETE("goal/{goalId}")
+ suspend fun deleteGoal(
+ @Path("goalId") id: Int
+ ): ResponseGoalDeleted
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/KakaoAuthService.kt b/app/src/main/java/org/keepgoeat/data/service/KakaoAuthService.kt
new file mode 100644
index 00000000..d04c3bc2
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/KakaoAuthService.kt
@@ -0,0 +1,78 @@
+package org.keepgoeat.data.service
+
+import android.content.Context
+import com.kakao.sdk.auth.model.OAuthToken
+import com.kakao.sdk.user.UserApiClient
+import dagger.hilt.android.qualifiers.ActivityContext
+import org.keepgoeat.domain.model.AccountInfo
+import org.keepgoeat.presentation.type.LoginPlatformType
+import timber.log.Timber
+import javax.inject.Inject
+
+class KakaoAuthService @Inject constructor(
+ @ActivityContext private val context: Context,
+ private val client: UserApiClient,
+) {
+ private val isKakaoTalkLoginAvailable: Boolean
+ get() = client.isKakaoTalkLoginAvailable(context)
+
+ fun loginKakao(
+ loginListener: ((LoginPlatformType, String) -> Unit),
+ accountListener: ((AccountInfo) -> Unit)
+ ) {
+ val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
+ if (error != null) handleLoginError(error)
+ else if (token != null) handleLoginSuccess(token, loginListener, accountListener)
+ }
+
+ if (isKakaoTalkLoginAvailable) client.loginWithKakaoTalk(context, callback = callback)
+ else client.loginWithKakaoAccount(context, callback = callback)
+ }
+
+ private fun handleLoginError(throwable: Throwable) {
+ val kakaoType = if (isKakaoTalkLoginAvailable) "์นด์นด์คํก" else "์นด์นด์ค ๊ณ์ "
+ Timber.d("${kakaoType}์ผ๋ก ๋ก๊ทธ์ธ ์คํจ (${throwable.message})")
+ }
+
+ private fun handleLoginSuccess(
+ oAuthToken: OAuthToken,
+ loginListener: ((LoginPlatformType, String) -> Unit),
+ accountListener: ((AccountInfo) -> Unit),
+ ) {
+ client.me { user, error ->
+ Timber.d(oAuthToken.accessToken)
+ loginListener(LoginPlatformType.KAKAO, oAuthToken.accessToken)
+ if (error != null) Timber.e("kakao ์ฌ์ฉ์ ์ ๋ณด ์์ฒญ ์คํจ $error")
+ else if (user != null) {
+ accountListener(
+ AccountInfo(
+ user.kakaoAccount?.profile?.nickname ?: "",
+ user.kakaoAccount?.email ?: ""
+ )
+ )
+ }
+ }
+ }
+
+ fun logoutKakao(logoutListener: (() -> Unit)) {
+ client.logout { error ->
+ if (error == null) {
+ Timber.i("๋ก๊ทธ์์ ์ฑ๊ณต. SDK์์ ํ ํฐ ์ญ์ ๋จ")
+ logoutListener()
+ } else {
+ Timber.e("๋ก๊ทธ์์ ์คํจ. SDK์์ ํ ํฐ ์ญ์ ๋จ($error)")
+ }
+ }
+ }
+
+ fun deleteAccountKakao(deleteAccountListener: (() -> Unit)) {
+ client.unlink { error ->
+ if (error == null) {
+ Timber.d("์ฐ๊ฒฐ ๋๊ธฐ ์ฑ๊ณต. SDK์์ ํ ํฐ ์ญ์ ๋จ")
+ deleteAccountListener()
+ } else {
+ Timber.e("์ฐ๊ฒฐ ๋๊ธฐ ์คํจ($error)")
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/NaverAuthService.kt b/app/src/main/java/org/keepgoeat/data/service/NaverAuthService.kt
new file mode 100644
index 00000000..aff9adbb
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/NaverAuthService.kt
@@ -0,0 +1,102 @@
+package org.keepgoeat.data.service
+
+import android.content.Context
+import com.navercorp.nid.NaverIdLoginSDK
+import com.navercorp.nid.oauth.NidOAuthLogin
+import com.navercorp.nid.oauth.OAuthLoginCallback
+import com.navercorp.nid.profile.NidProfileCallback
+import com.navercorp.nid.profile.data.NidProfileResponse
+import dagger.hilt.android.qualifiers.ActivityContext
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.domain.model.AccountInfo
+import org.keepgoeat.presentation.type.LoginPlatformType
+import timber.log.Timber
+import javax.inject.Inject
+
+class NaverAuthService @Inject constructor(
+ @ActivityContext private val context: Context,
+) {
+ init {
+ NaverIdLoginSDK.initialize(
+ context, BuildConfig.NAVER_CLIENT_ID, BuildConfig.NAVER_CLIENT_SECRETE,
+ CLIENT_NAME
+ )
+ }
+
+ fun loginNaver(
+ loginListener: ((LoginPlatformType, String) -> Unit),
+ accountListener: (AccountInfo) -> Unit
+ ) {
+ val oauthLoginCallback = object : OAuthLoginCallback {
+ override fun onSuccess() {
+ val accessToken = requireNotNull(NaverIdLoginSDK.getAccessToken())
+ Timber.d(accessToken)
+ loginListener(LoginPlatformType.NAVER, accessToken)
+ getAccountInfo(accountListener)
+ }
+
+ override fun onFailure(httpStatus: Int, message: String) {
+ Timber.i(NaverIdLoginSDK.getLastErrorCode().code)
+ Timber.i(NaverIdLoginSDK.getLastErrorDescription())
+ }
+
+ override fun onError(errorCode: Int, message: String) {
+ onFailure(errorCode, message)
+ }
+ }
+ NaverIdLoginSDK.authenticate(
+ context, oauthLoginCallback
+ )
+ }
+
+ fun getAccountInfo(accountListener: (AccountInfo) -> Unit) {
+ NidOAuthLogin().callProfileApi(object : NidProfileCallback {
+ override fun onSuccess(result: NidProfileResponse) {
+ accountListener(
+ AccountInfo(
+ result.profile?.name ?: "",
+ result.profile?.email ?: ""
+ )
+ )
+ }
+
+ override fun onFailure(httpStatus: Int, message: String) {
+ Timber.i("Error : $httpStatus, message : $message")
+ }
+
+ override fun onError(errorCode: Int, message: String) {
+ onFailure(errorCode, message)
+ }
+ })
+ }
+
+ fun logoutNaver(logoutListener: (() -> Unit)) {
+ NaverIdLoginSDK.logout()
+ logoutListener()
+ }
+
+ fun deleteAccountNaver(deleteAccountListener: (() -> Unit)) {
+ NidOAuthLogin().callDeleteTokenApi(
+ context,
+ object : OAuthLoginCallback {
+ override fun onSuccess() {
+ Timber.d("์ฐ๊ฒฐ ๋๊ธฐ ์ฑ๊ณต. SDK์์ ํ ํฐ ์ญ์ ๋จ")
+ deleteAccountListener()
+ }
+
+ override fun onFailure(httpStatus: Int, message: String) {
+ Timber.d("errorCode: ${NaverIdLoginSDK.getLastErrorCode().code}")
+ Timber.d("errorDesc: ${NaverIdLoginSDK.getLastErrorDescription()}")
+ }
+
+ override fun onError(errorCode: Int, message: String) {
+ onFailure(errorCode, message)
+ }
+ }
+ )
+ }
+
+ companion object {
+ private const val CLIENT_NAME = "ํต๊ณ ์"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/UserService.kt b/app/src/main/java/org/keepgoeat/data/service/UserService.kt
new file mode 100644
index 00000000..1dce3989
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/UserService.kt
@@ -0,0 +1,9 @@
+package org.keepgoeat.data.service
+
+import org.keepgoeat.data.model.response.ResponseUserInfo
+import retrofit2.http.GET
+
+interface UserService {
+ @GET("mypage")
+ suspend fun fetchUserInfo(): ResponseUserInfo
+}
diff --git a/app/src/main/java/org/keepgoeat/data/service/VersionService.kt b/app/src/main/java/org/keepgoeat/data/service/VersionService.kt
new file mode 100644
index 00000000..70e6159b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/data/service/VersionService.kt
@@ -0,0 +1,13 @@
+package org.keepgoeat.data.service
+
+import org.keepgoeat.data.model.response.ResponseVersion
+import retrofit2.http.GET
+import retrofit2.http.Query
+
+interface VersionService {
+ /** ์ต์ ๊ฐ์ ์
๋ฐ์ดํธ ๋ฒ์ ์ ๋ถ๋ฌ์ค๋ ํจ์ */
+ @GET("ver")
+ suspend fun getForcedUpdateVersion(
+ @Query("client") client: String,
+ ): ResponseVersion
+}
diff --git a/app/src/main/java/org/keepgoeat/di/NetworkModule.kt b/app/src/main/java/org/keepgoeat/di/NetworkModule.kt
index 823d5dc0..76419ce8 100644
--- a/app/src/main/java/org/keepgoeat/di/NetworkModule.kt
+++ b/app/src/main/java/org/keepgoeat/di/NetworkModule.kt
@@ -1,5 +1,7 @@
package org.keepgoeat.di
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import dagger.Module
import dagger.Provides
@@ -7,10 +9,13 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
+import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
+import org.keepgoeat.BuildConfig
import org.keepgoeat.BuildConfig.DEBUG
+import org.keepgoeat.data.interceptor.AuthInterceptor
import retrofit2.Retrofit
import java.util.concurrent.TimeUnit
import javax.inject.Singleton
@@ -28,27 +33,37 @@ object NetworkModule {
ignoreUnknownKeys = true
}
+ @Provides
+ @Singleton
+ fun provideGson(): Gson = GsonBuilder().setLenient().create()
+
@ExperimentalSerializationApi
@Provides
@Singleton
fun provideRetrofit(client: OkHttpClient, json: Json): Retrofit = Retrofit.Builder()
- .baseUrl("https://reqres.in/") // TODO BaseUrl ๋ณ๊ฒฝ ๋ฐ BuildConfig ๋ณ์ ์ฌ์ฉ
+ .baseUrl(BuildConfig.KGE_BASE_URL)
.client(client)
.addConverterFactory(json.asConverterFactory(requireNotNull("application/json".toMediaTypeOrNull())))
.build()
@Provides
@Singleton
- fun provideOkHttpClientBuilder(): OkHttpClient =
+ fun provideAuthInterceptor(interceptor: AuthInterceptor): Interceptor = interceptor
+
+ @Provides
+ @Singleton
+ fun provideOkHttpClientBuilder(
+ interceptor: AuthInterceptor,
+ ): OkHttpClient =
OkHttpClient.Builder().apply {
connectTimeout(10, TimeUnit.SECONDS)
writeTimeout(10, TimeUnit.SECONDS)
readTimeout(10, TimeUnit.SECONDS)
+ addInterceptor(interceptor)
if (DEBUG) addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
)
- // TODO AuthInterceptor ์ถ๊ฐ
}.build()
}
diff --git a/app/src/main/java/org/keepgoeat/di/RepositoryModule.kt b/app/src/main/java/org/keepgoeat/di/RepositoryModule.kt
index d3d75e7f..67b8d879 100644
--- a/app/src/main/java/org/keepgoeat/di/RepositoryModule.kt
+++ b/app/src/main/java/org/keepgoeat/di/RepositoryModule.kt
@@ -4,8 +4,14 @@ import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
-import org.keepgoeat.data.repository.DummyRepositoryImpl
-import org.keepgoeat.domain.repository.DummyRepository
+import org.keepgoeat.data.repository.AuthRepositoryImpl
+import org.keepgoeat.data.repository.GoalRepositoryImpl
+import org.keepgoeat.data.repository.UserRepositoryImpl
+import org.keepgoeat.data.repository.VersionRepositoryImpl
+import org.keepgoeat.domain.repository.AuthRepository
+import org.keepgoeat.domain.repository.GoalRepository
+import org.keepgoeat.domain.repository.UserRepository
+import org.keepgoeat.domain.repository.VersionRepository
import javax.inject.Singleton
@Module
@@ -13,7 +19,25 @@ import javax.inject.Singleton
interface RepositoryModule {
@Binds
@Singleton
- fun bindDummyRepository(
- dummyRepositoryImpl: DummyRepositoryImpl,
- ): DummyRepository
+ fun bindGoalRepository(
+ goalRepositoryImpl: GoalRepositoryImpl,
+ ): GoalRepository
+
+ @Binds
+ @Singleton
+ fun bindAuthRepository(
+ authRepositoryImpl: AuthRepositoryImpl,
+ ): AuthRepository
+
+ @Binds
+ @Singleton
+ fun bindUserRepository(
+ userRepositoryImpl: UserRepositoryImpl,
+ ): UserRepository
+
+ @Binds
+ @Singleton
+ fun bindVersionRepository(
+ versionRepositoryImpl: VersionRepositoryImpl
+ ): VersionRepository
}
diff --git a/app/src/main/java/org/keepgoeat/di/ServiceModule.kt b/app/src/main/java/org/keepgoeat/di/ServiceModule.kt
index e1fdd008..489f197b 100644
--- a/app/src/main/java/org/keepgoeat/di/ServiceModule.kt
+++ b/app/src/main/java/org/keepgoeat/di/ServiceModule.kt
@@ -4,7 +4,10 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
-import org.keepgoeat.data.service.DummyService
+import org.keepgoeat.data.service.AuthService
+import org.keepgoeat.data.service.GoalService
+import org.keepgoeat.data.service.UserService
+import org.keepgoeat.data.service.VersionService
import retrofit2.Retrofit
import javax.inject.Singleton
@@ -13,6 +16,21 @@ import javax.inject.Singleton
object ServiceModule {
@Singleton
@Provides
- fun provideDummyService(retrofit: Retrofit): DummyService =
- retrofit.create(DummyService::class.java)
+ fun provideGoalService(retrofit: Retrofit): GoalService =
+ retrofit.create(GoalService::class.java)
+
+ @Singleton
+ @Provides
+ fun provideAuthService(retrofit: Retrofit): AuthService =
+ retrofit.create(AuthService::class.java)
+
+ @Singleton
+ @Provides
+ fun provideUserService(retrofit: Retrofit): UserService =
+ retrofit.create(UserService::class.java)
+
+ @Singleton
+ @Provides
+ fun provideVersionService(retrofit: Retrofit): VersionService =
+ retrofit.create(VersionService::class.java)
}
diff --git a/app/src/main/java/org/keepgoeat/di/SignModule.kt b/app/src/main/java/org/keepgoeat/di/SignModule.kt
new file mode 100644
index 00000000..dd87c9a6
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/di/SignModule.kt
@@ -0,0 +1,31 @@
+package org.keepgoeat.di
+
+import android.content.Context
+import com.kakao.sdk.user.UserApiClient
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.qualifiers.ActivityContext
+import dagger.hilt.android.scopes.ActivityScoped
+import org.keepgoeat.data.service.KakaoAuthService
+import org.keepgoeat.data.service.NaverAuthService
+
+@Module
+@InstallIn(ActivityComponent::class)
+object SignModule {
+ @Provides
+ @ActivityScoped
+ fun provideUserApiClient(): UserApiClient = UserApiClient.instance
+
+ @Provides
+ fun provideKakaoSignService(
+ @ActivityContext context: Context,
+ client: UserApiClient,
+ ) = KakaoAuthService(context, client)
+
+ @Provides
+ fun provideNaverSignService(
+ @ActivityContext context: Context,
+ ) = NaverAuthService(context)
+}
diff --git a/app/src/main/java/org/keepgoeat/domain/model/DummyData.kt b/app/src/main/java/org/keepgoeat/domain/model/AccountInfo.kt
similarity index 66%
rename from app/src/main/java/org/keepgoeat/domain/model/DummyData.kt
rename to app/src/main/java/org/keepgoeat/domain/model/AccountInfo.kt
index 828500d1..692d59c0 100644
--- a/app/src/main/java/org/keepgoeat/domain/model/DummyData.kt
+++ b/app/src/main/java/org/keepgoeat/domain/model/AccountInfo.kt
@@ -1,7 +1,6 @@
package org.keepgoeat.domain.model
-data class DummyData(
- val email: String,
- val id: String,
+data class AccountInfo(
val name: String,
+ val email: String,
)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/ArchivedGoal.kt b/app/src/main/java/org/keepgoeat/domain/model/ArchivedGoal.kt
new file mode 100644
index 00000000..3559293f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/ArchivedGoal.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.domain.model
+
+import org.keepgoeat.presentation.type.EatingType
+
+data class ArchivedGoal(
+ val id: Int,
+ val goalContent: String,
+ val eatingType: EatingType,
+ val startedAt: String,
+ val archivedAt: String?,
+ val totalCount: Int,
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/AuthInfo.kt b/app/src/main/java/org/keepgoeat/domain/model/AuthInfo.kt
new file mode 100644
index 00000000..66745241
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/AuthInfo.kt
@@ -0,0 +1,10 @@
+package org.keepgoeat.domain.model
+
+import org.keepgoeat.domain.type.SignType
+
+data class AuthInfo(
+ val signType: SignType,
+ val email: String,
+ val accessToken: String,
+ val refreshToken: String,
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/GoalDetail.kt b/app/src/main/java/org/keepgoeat/domain/model/GoalDetail.kt
new file mode 100644
index 00000000..2007fe39
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/GoalDetail.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.domain.model
+
+import org.keepgoeat.presentation.type.EatingType
+
+data class GoalDetail(
+ val id: Int,
+ val eatingType: EatingType,
+ val thisMonthCount: Int,
+ val lastMonthCount: Int,
+ val food: String,
+ val criterion: String
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/GoalSticker.kt b/app/src/main/java/org/keepgoeat/domain/model/GoalSticker.kt
new file mode 100644
index 00000000..29d585ae
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/GoalSticker.kt
@@ -0,0 +1,6 @@
+package org.keepgoeat.domain.model
+
+data class GoalSticker(
+ val id: Int,
+ val isDone: Boolean,
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/HomeContent.kt b/app/src/main/java/org/keepgoeat/domain/model/HomeContent.kt
new file mode 100644
index 00000000..7ef03c2a
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/HomeContent.kt
@@ -0,0 +1,6 @@
+package org.keepgoeat.domain.model
+
+data class HomeContent(
+ val cheeringMessage: String,
+ val goals: List
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/HomeGoal.kt b/app/src/main/java/org/keepgoeat/domain/model/HomeGoal.kt
new file mode 100644
index 00000000..4205788a
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/HomeGoal.kt
@@ -0,0 +1,13 @@
+package org.keepgoeat.domain.model
+
+import org.keepgoeat.presentation.type.HomeGoalViewType
+
+data class HomeGoal(
+ val id: Int,
+ val goalTitle: String,
+ val goalCriterion: String,
+ val isMore: Boolean,
+ val isAchieved: Boolean,
+ val thisMonthCount: Int,
+ val type: HomeGoalViewType
+)
diff --git a/app/src/main/java/org/keepgoeat/domain/model/UserInfo.kt b/app/src/main/java/org/keepgoeat/domain/model/UserInfo.kt
new file mode 100644
index 00000000..6762a75d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/model/UserInfo.kt
@@ -0,0 +1,11 @@
+package org.keepgoeat.domain.model
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class UserInfo(
+ val name: String,
+ val email: String,
+ val archivedGoalCount: Int,
+) : Parcelable
diff --git a/app/src/main/java/org/keepgoeat/domain/repository/AuthRepository.kt b/app/src/main/java/org/keepgoeat/domain/repository/AuthRepository.kt
new file mode 100644
index 00000000..ce9c5c44
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/repository/AuthRepository.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.domain.repository
+
+import org.keepgoeat.data.model.request.RequestAuth
+import org.keepgoeat.data.model.response.ResponseRefresh
+import org.keepgoeat.data.model.response.ResponseWithdraw
+import org.keepgoeat.domain.model.AuthInfo
+
+interface AuthRepository {
+ suspend fun login(requestAuth: RequestAuth): Result
+ suspend fun refresh(): Result
+ suspend fun deleteAccount(): Result
+}
diff --git a/app/src/main/java/org/keepgoeat/domain/repository/DummyRepository.kt b/app/src/main/java/org/keepgoeat/domain/repository/DummyRepository.kt
deleted file mode 100644
index 80a2d465..00000000
--- a/app/src/main/java/org/keepgoeat/domain/repository/DummyRepository.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.keepgoeat.domain.repository
-
-interface DummyRepository {
- suspend fun uploadDummy(name: String, email: String)
-}
diff --git a/app/src/main/java/org/keepgoeat/domain/repository/GoalRepository.kt b/app/src/main/java/org/keepgoeat/domain/repository/GoalRepository.kt
new file mode 100644
index 00000000..68aea78f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/repository/GoalRepository.kt
@@ -0,0 +1,31 @@
+package org.keepgoeat.domain.repository
+
+import org.keepgoeat.data.model.response.*
+import org.keepgoeat.domain.model.GoalDetail
+import org.keepgoeat.domain.model.ArchivedGoal
+import org.keepgoeat.domain.model.HomeContent
+
+interface GoalRepository {
+ suspend fun achieveGoal(
+ goalId: Int,
+ isAchieved: Boolean
+ ): Result
+
+ suspend fun uploadGoalContent(
+ food: String,
+ criterion: String,
+ isMore: Boolean
+ ): Result
+
+ suspend fun editGoalContent(
+ id: Int,
+ food: String,
+ criterion: String
+ ): Result
+
+ suspend fun fetchHomeContent(): Result
+ suspend fun fetchGoalDetail(goalId: Int): Result
+ suspend fun fetchArchivedGoal(sortType: String): Result>
+ suspend fun keepGoal(id: Int): Result
+ suspend fun deleteGoal(id: Int): Result
+}
diff --git a/app/src/main/java/org/keepgoeat/domain/repository/UserRepository.kt b/app/src/main/java/org/keepgoeat/domain/repository/UserRepository.kt
new file mode 100644
index 00000000..f32ca764
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/repository/UserRepository.kt
@@ -0,0 +1,7 @@
+package org.keepgoeat.domain.repository
+
+import org.keepgoeat.domain.model.UserInfo
+
+interface UserRepository {
+ suspend fun fetchUserInfo(): Result
+}
diff --git a/app/src/main/java/org/keepgoeat/domain/repository/VersionRepository.kt b/app/src/main/java/org/keepgoeat/domain/repository/VersionRepository.kt
new file mode 100644
index 00000000..c413cfbc
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/repository/VersionRepository.kt
@@ -0,0 +1,7 @@
+package org.keepgoeat.domain.repository
+
+import org.keepgoeat.data.model.response.ResponseVersion
+
+interface VersionRepository {
+ suspend fun getForcedUpdateVersion(clientType: String): Result
+}
diff --git a/app/src/main/java/org/keepgoeat/domain/type/SignType.kt b/app/src/main/java/org/keepgoeat/domain/type/SignType.kt
new file mode 100644
index 00000000..92292bb3
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/domain/type/SignType.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.domain.type
+
+enum class SignType(val typeStr: String) {
+ SIGN_UP("signup"), SIGN_IN("signin")
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/MainActivity.kt b/app/src/main/java/org/keepgoeat/presentation/MainActivity.kt
deleted file mode 100644
index 24767676..00000000
--- a/app/src/main/java/org/keepgoeat/presentation/MainActivity.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.keepgoeat.presentation
-
-import org.keepgoeat.R
-import org.keepgoeat.databinding.ActivityMainBinding
-import org.keepgoeat.util.binding.BindingActivity
-
-class MainActivity : BindingActivity(R.layout.activity_main)
diff --git a/app/src/main/java/org/keepgoeat/presentation/SplashActivity.kt b/app/src/main/java/org/keepgoeat/presentation/SplashActivity.kt
new file mode 100644
index 00000000..8ea98721
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/SplashActivity.kt
@@ -0,0 +1,45 @@
+package org.keepgoeat.presentation
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import org.keepgoeat.R
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.databinding.ActivitySplashBinding
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.onboarding.OnboardingActivity
+import org.keepgoeat.presentation.sign.SignActivity
+import org.keepgoeat.presentation.base.screen.BindingActivity
+
+@AndroidEntryPoint
+class SplashActivity : BindingActivity(R.layout.activity_splash) {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ installSplashScreen()
+ super.onCreate(savedInstanceState)
+ loadSplashScreen()
+ }
+
+ private fun loadSplashScreen() {
+ lifecycleScope.launch {
+ delay(1000L)
+ moveToNext()
+ }
+ }
+
+ private fun moveToNext() {
+ val storage = KGEDataSource(this)
+ val nextScreen =
+ if (storage.isLogin) {
+ if (storage.isClickedOnboardingButton) HomeActivity::class.java
+ else OnboardingActivity::class.java
+ } else {
+ SignActivity::class.java
+ }
+ startActivity(Intent(this, nextScreen))
+ finish()
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingActivity.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingActivity.kt
new file mode 100644
index 00000000..189a0635
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingActivity.kt
@@ -0,0 +1,46 @@
+package org.keepgoeat.presentation.base.screen
+
+import android.os.Bundle
+import androidx.annotation.LayoutRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.databinding.DataBindingUtil
+import androidx.databinding.ViewDataBinding
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import com.google.android.material.snackbar.Snackbar
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.util.KGESnackbar
+import org.keepgoeat.util.NetworkMonitor
+
+abstract class BindingActivity(@LayoutRes private val layoutRes: Int) :
+ AppCompatActivity() {
+ lateinit var binding: B
+ private var snackbar: KGESnackbar? = null
+ private val _isConnectedNetwork = MutableStateFlow(false)
+ val isConnectedNetwork get() = _isConnectedNetwork.asStateFlow()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = DataBindingUtil.setContentView(this, layoutRes)
+ snackbar = KGESnackbar(
+ binding.root,
+ getString(R.string.network_error_snackbar_message),
+ Snackbar.LENGTH_INDEFINITE,
+ true
+ )
+ collectNetworkState()
+ }
+
+ private fun collectNetworkState() {
+ NetworkMonitor(this, lifecycleScope).isConnected.flowWithLifecycle(lifecycle)
+ .onEach { isConnected ->
+ if (isConnected) snackbar?.dismiss()
+ else snackbar?.show()
+ _isConnectedNetwork.value = isConnected
+ }.launchIn(lifecycleScope)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingBottomSheetDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingBottomSheetDialogFragment.kt
new file mode 100644
index 00000000..fe8bec21
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingBottomSheetDialogFragment.kt
@@ -0,0 +1,30 @@
+package org.keepgoeat.presentation.base.screen
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.LayoutRes
+import androidx.databinding.DataBindingUtil
+import androidx.databinding.ViewDataBinding
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+
+abstract class BindingBottomSheetDialogFragment(@LayoutRes private val layoutRes: Int) :
+ BottomSheetDialogFragment() {
+ private var _binding: B? = null
+ val binding get() = requireNotNull(_binding!!) { "${this::class.java.simpleName}์์ ์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View {
+ _binding = DataBindingUtil.inflate(inflater, layoutRes, container, false)
+ return binding.root
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingDialogFragment.kt
new file mode 100644
index 00000000..46e3f2e9
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingDialogFragment.kt
@@ -0,0 +1,40 @@
+package org.keepgoeat.presentation.base.screen
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import androidx.annotation.LayoutRes
+import androidx.databinding.DataBindingUtil
+import androidx.databinding.ViewDataBinding
+import androidx.fragment.app.DialogFragment
+
+abstract class BindingDialogFragment(@LayoutRes private val layoutRes: Int) :
+ DialogFragment() {
+ private var _binding: B? = null
+ val binding get() = requireNotNull(_binding!!) { "${this::class.java.simpleName}์์ ์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.WRAP_CONTENT
+ )
+ dialog?.window?.setBackgroundDrawableResource(android.R.color.transparent)
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View {
+ _binding = DataBindingUtil.inflate(inflater, layoutRes, container, false)
+ return binding.root
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/binding/BindingFragment.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingFragment.kt
similarity index 83%
rename from app/src/main/java/org/keepgoeat/util/binding/BindingFragment.kt
rename to app/src/main/java/org/keepgoeat/presentation/base/screen/BindingFragment.kt
index d0553dbb..08326826 100644
--- a/app/src/main/java/org/keepgoeat/util/binding/BindingFragment.kt
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/BindingFragment.kt
@@ -1,4 +1,4 @@
-package org.keepgoeat.util.binding
+package org.keepgoeat.presentation.base.screen
import android.os.Bundle
import android.view.LayoutInflater
@@ -9,7 +9,7 @@ import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
-abstract class BindingFragment(@LayoutRes private val layoutResId: Int) :
+abstract class BindingFragment(@LayoutRes private val layoutRes: Int) :
Fragment() {
private var _binding: B? = null
val binding get() = requireNotNull(_binding!!) { "${this::class.java.simpleName}์์ ์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }
@@ -19,7 +19,7 @@ abstract class BindingFragment(@LayoutRes private val layou
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
- _binding = DataBindingUtil.inflate(inflater, layoutResId, container, false)
+ _binding = DataBindingUtil.inflate(inflater, layoutRes, container, false)
return binding.root
}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelActivity.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelActivity.kt
new file mode 100644
index 00000000..b591898a
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelActivity.kt
@@ -0,0 +1,22 @@
+package org.keepgoeat.presentation.base.screen
+
+import androidx.annotation.LayoutRes
+import androidx.databinding.ViewDataBinding
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+
+abstract class MixpanelActivity(
+ @LayoutRes private val layoutRes: Int,
+ private val screenName: String,
+) : BindingActivity(layoutRes) {
+ abstract val viewModel: MixpanelViewModel
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.startRecodingScreenTime()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ viewModel.stopRecodingScreenTime(screenName)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelBottomSheetDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelBottomSheetDialogFragment.kt
new file mode 100644
index 00000000..df2caf92
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/screen/MixpanelBottomSheetDialogFragment.kt
@@ -0,0 +1,22 @@
+package org.keepgoeat.presentation.base.screen
+
+import androidx.annotation.LayoutRes
+import androidx.databinding.ViewDataBinding
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+
+abstract class MixpanelBottomSheetDialogFragment(
+ @LayoutRes private val layoutRes: Int,
+ private val screenName: String,
+) : BindingBottomSheetDialogFragment(layoutRes) {
+ abstract val viewModel: MixpanelViewModel
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.startRecodingScreenTime()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ viewModel.stopRecodingScreenTime(screenName)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/BaseViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/BaseViewModel.kt
new file mode 100644
index 00000000..58dec14d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/BaseViewModel.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.presentation.base.viewmodel
+
+import androidx.lifecycle.ViewModel
+
+abstract class BaseViewModel : ViewModel()
diff --git a/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/MixpanelViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/MixpanelViewModel.kt
new file mode 100644
index 00000000..0cf2ca28
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/base/viewmodel/MixpanelViewModel.kt
@@ -0,0 +1,17 @@
+package org.keepgoeat.presentation.base.viewmodel
+
+import org.keepgoeat.util.mixpanel.MixpanelProvider
+import javax.inject.Inject
+
+abstract class MixpanelViewModel : BaseViewModel() {
+ @Inject
+ lateinit var mixpanelProvider: MixpanelProvider
+
+ fun startRecodingScreenTime() {
+ mixpanelProvider.startRecodingScreenTime()
+ }
+
+ fun stopRecodingScreenTime(screenName: String) {
+ mixpanelProvider.stopRecodingScreenTime(screenName)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/common/WebViewActivity.kt b/app/src/main/java/org/keepgoeat/presentation/common/WebViewActivity.kt
new file mode 100644
index 00000000..113131ec
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/common/WebViewActivity.kt
@@ -0,0 +1,45 @@
+package org.keepgoeat.presentation.common
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.webkit.WebChromeClient
+import android.webkit.WebViewClient
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityWebViewBinding
+import org.keepgoeat.presentation.base.screen.BindingActivity
+
+class WebViewActivity : BindingActivity(R.layout.activity_web_view) {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ initView()
+ }
+
+ @SuppressLint("SetJavaScriptEnabled")
+ private fun initView() {
+ binding.webView.apply {
+ webViewClient = WebViewClient()
+ webChromeClient = WebChromeClient()
+
+ settings.apply {
+ javaScriptEnabled = true
+ javaScriptCanOpenWindowsAutomatically = true
+ loadWithOverviewMode = true
+ useWideViewPort = true
+ domStorageEnabled = true
+ setSupportZoom(true)
+ }
+
+ intent.getStringExtra(ARG_WEB_VIEW_LINK)?.let { loadUrl(it) }
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ overridePendingTransition(0, 0)
+ }
+
+ companion object {
+ const val ARG_WEB_VIEW_LINK = "link"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/detail/GoalDeleteBottomDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDeleteBottomDialogFragment.kt
new file mode 100644
index 00000000..1fc6408b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDeleteBottomDialogFragment.kt
@@ -0,0 +1,34 @@
+package org.keepgoeat.presentation.detail
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.R
+import org.keepgoeat.databinding.DialogBottomGoalDeleteBinding
+import org.keepgoeat.presentation.base.screen.MixpanelBottomSheetDialogFragment
+
+@AndroidEntryPoint
+class GoalDeleteBottomDialogFragment :
+ MixpanelBottomSheetDialogFragment(
+ R.layout.dialog_bottom_goal_delete, SCREEN_NAME
+ ) {
+ override val viewModel: GoalDetailViewModel by activityViewModels()
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.viewModel = viewModel
+
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.btnNo.setOnClickListener {
+ dismiss()
+ }
+ }
+
+ companion object {
+ private const val SCREEN_NAME = "goal delete"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailActivity.kt b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailActivity.kt
new file mode 100644
index 00000000..2b33f3f7
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailActivity.kt
@@ -0,0 +1,152 @@
+package org.keepgoeat.presentation.detail
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityGoalDetailBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.detail.GoalDetailViewModel.Companion.CELL_COUNT
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.model.GoalContent
+import org.keepgoeat.presentation.my.archive.ArchivedGoalActivity
+import org.keepgoeat.presentation.my.archive.ArchivedGoalActivity.Companion.ARG_IS_ENTERED_FROM_KEEP
+import org.keepgoeat.presentation.setting.GoalSettingActivity
+import org.keepgoeat.presentation.setting.GoalSettingActivity.Companion.ARG_GOAL_CONTENT
+import org.keepgoeat.presentation.setting.GoalSettingActivity.Companion.ARG_IS_UPDATED
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.presentation.type.RecyclerLayoutType
+import org.keepgoeat.util.ItemDecorationUtil
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.showToast
+import org.keepgoeat.util.safeValueOf
+
+@AndroidEntryPoint
+class GoalDetailActivity :
+ MixpanelActivity(R.layout.activity_goal_detail, SCREEN_NAME) {
+ override val viewModel: GoalDetailViewModel by viewModels()
+ private lateinit var adapter: GoalStickerListAdapter
+ private var isUpdated = false
+ private val callback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ moveToHome()
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ intent.let {
+ val eatingType = safeValueOf(it.getStringExtra(ARG_EATING_TYPE)) ?: return
+ binding.eatingType = eatingType
+ adapter = GoalStickerListAdapter(eatingType, CELL_COUNT)
+ val goalId = it.getIntExtra(ARG_GOAL_ID, -1)
+ viewModel.fetchGoalDetailInfo(goalId)
+ isUpdated = it.getBooleanExtra(ARG_IS_UPDATED, false)
+ if (isUpdated) this.onBackPressedDispatcher.addCallback(this, callback)
+ }
+
+ initLayout()
+ addListeners()
+ collectData()
+ }
+
+ private fun initLayout() {
+ binding.rvGoalCard.apply {
+ addItemDecoration(
+ ItemDecorationUtil(
+ CARD_ITEM_SPACE,
+ Pair(CARD_MATRIX_ROW, CARD_MATRIX_COL),
+ RecyclerLayoutType.GRID
+ )
+ )
+ clipToOutline = true
+ adapter = this@GoalDetailActivity.adapter
+ }
+ }
+
+ private fun addListeners() {
+ binding.ivBack.setOnClickListener {
+ if (isUpdated) moveToHome()
+ else finish()
+ }
+ binding.ivKeep.setOnClickListener {
+ showGoalKeepDialog()
+ }
+ binding.ivEdit.setOnClickListener {
+ viewModel.goalDetail.value?.let { detail ->
+ val content = GoalContent(detail.id, detail.food, detail.criterion)
+ Intent(this, GoalSettingActivity::class.java).apply {
+ putExtra(ARG_GOAL_CONTENT, content)
+ putExtra(ARG_EATING_TYPE, detail.eatingType.name)
+ }.also {
+ startActivity(it)
+ }
+ }
+ }
+ }
+
+ private fun collectData() {
+ viewModel.goalStickers.flowWithLifecycle(lifecycle).onEach { stickers ->
+ adapter.submitList(stickers)
+ }.launchIn(lifecycleScope)
+ viewModel.keepState.flowWithLifecycle(lifecycle).onEach { keepState ->
+ when (keepState) {
+ is UiState.Success -> {
+ showToast(getString(R.string.goal_detail_success_goal_keep_toast_message))
+ Intent(this, ArchivedGoalActivity::class.java).apply {
+ putExtra(ARG_IS_ENTERED_FROM_KEEP, true)
+ putExtra(
+ ARG_HOME_GOAL_COUNT,
+ intent.getIntExtra(ARG_HOME_GOAL_COUNT, -1) - 1
+ )
+ }.also {
+ startActivity(it)
+ finish()
+ }
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ viewModel.deleteState.flowWithLifecycle(lifecycle).onEach { deleteState ->
+ when (deleteState) {
+ is UiState.Success -> {
+ showToast(getString(R.string.goal_detail_success_goal_delete_toast_message))
+ startActivity(Intent(this, HomeActivity::class.java))
+ finish()
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun showGoalKeepDialog() {
+ intent?.let {
+ GoalKeepBottomDialogFragment().show(supportFragmentManager, "goalKeepDialog")
+ }
+ }
+
+ private fun moveToHome() {
+ val intent = Intent(this, HomeActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivity(intent)
+ }
+
+ companion object {
+ private const val CARD_ITEM_SPACE = 2
+ private const val CARD_MATRIX_ROW = 5
+ private const val CARD_MATRIX_COL = 7
+ const val ARG_EATING_TYPE = "eatingType"
+ const val ARG_GOAL_ID = "goalId"
+ const val ARG_HOME_GOAL_COUNT = "homeGoalCount"
+ private const val SCREEN_NAME = "goal detail"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailViewModel.kt
new file mode 100644
index 00000000..3d2e21d2
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/detail/GoalDetailViewModel.kt
@@ -0,0 +1,84 @@
+package org.keepgoeat.presentation.detail
+
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import org.keepgoeat.domain.model.GoalDetail
+import org.keepgoeat.domain.model.GoalSticker
+import org.keepgoeat.domain.repository.GoalRepository
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.mixpanel.GoalEvent
+import timber.log.Timber
+import javax.inject.Inject
+
+@HiltViewModel
+class GoalDetailViewModel @Inject constructor(
+ private val goalRepository: GoalRepository,
+) : MixpanelViewModel() {
+ private val _goalStickers = MutableStateFlow>(emptyList())
+ val goalStickers get() = _goalStickers.asStateFlow()
+ private val _goalDetail = MutableStateFlow(null)
+ val goalDetail get() = _goalDetail.asStateFlow()
+ private val _goalId = MutableStateFlow(-1)
+ val goalId get() = _goalId.asStateFlow()
+ private val _keepState = MutableStateFlow>(UiState.Loading)
+ val keepState get() = _keepState.asStateFlow()
+ private val _deleteState = MutableStateFlow>(UiState.Loading)
+ val deleteState get() = _deleteState.asStateFlow()
+
+ fun fetchGoalDetailInfo(goalId: Int) {
+ _goalId.value = goalId
+ viewModelScope.launch {
+ goalRepository.fetchGoalDetail(goalId).onSuccess { detail ->
+ _goalDetail.value = detail
+ _goalStickers.value = Array(CELL_COUNT) { idx ->
+ GoalSticker(idx, idx < detail.thisMonthCount)
+ }.toList()
+ }.onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+
+ fun keepGoal() {
+ viewModelScope.launch {
+ goalId.value.let { id ->
+ goalRepository.keepGoal(id).onSuccess { goalData ->
+ _keepState.value = UiState.Success(goalData.goalId)
+ mixpanelProvider.sendEvent(
+ GoalEvent.archiveGoal(
+ goalDetail.value?.food ?: "",
+ goalDetail.value?.criterion ?: ""
+ )
+ )
+ }.onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+ }
+
+ fun deleteGoal() {
+ viewModelScope.launch {
+ goalId.value.let { id ->
+ goalRepository.deleteGoal(id)
+ .onSuccess { deletedData ->
+ _deleteState.value = UiState.Success(deletedData.goalId)
+ with(mixpanelProvider) {
+ deleteGoal()
+ sendEvent(GoalEvent.deleteGoal(), false)
+ }
+ }.onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+ }
+
+ companion object {
+ const val CELL_COUNT = 35
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/detail/GoalKeepBottomDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/detail/GoalKeepBottomDialogFragment.kt
new file mode 100644
index 00000000..9d598d49
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/detail/GoalKeepBottomDialogFragment.kt
@@ -0,0 +1,56 @@
+package org.keepgoeat.presentation.detail
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.DialogBottomGoalKeepBinding
+import org.keepgoeat.presentation.base.screen.MixpanelBottomSheetDialogFragment
+import org.keepgoeat.util.UiState
+
+@AndroidEntryPoint
+class GoalKeepBottomDialogFragment : // TODO ๋ค์ด๋ฐ ์์ keep -> archive
+ MixpanelBottomSheetDialogFragment(
+ R.layout.dialog_bottom_goal_keep, SCREEN_NAME
+ ) {
+ override val viewModel: GoalDetailViewModel by activityViewModels()
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.viewModel = viewModel
+
+ addListeners()
+ collectData()
+ }
+
+ private fun addListeners() {
+ binding.tvDelete.setOnClickListener {
+ showGoalDeleteDialog()
+ }
+ }
+
+ private fun collectData() {
+ viewModel.keepState.flowWithLifecycle(lifecycle).onEach { keepState ->
+ when (keepState) {
+ is UiState.Success -> {
+ dismiss()
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun showGoalDeleteDialog() {
+ GoalDeleteBottomDialogFragment().show(parentFragmentManager, "goalDeleteDialog")
+ dismiss()
+ }
+
+ companion object {
+ private const val SCREEN_NAME = "goal archive"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/detail/GoalStickerListAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/detail/GoalStickerListAdapter.kt
new file mode 100644
index 00000000..6946d921
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/detail/GoalStickerListAdapter.kt
@@ -0,0 +1,46 @@
+package org.keepgoeat.presentation.detail
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.databinding.ItemGoalStickerBinding
+import org.keepgoeat.domain.model.GoalSticker
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.util.ItemDiffCallback
+import java.time.LocalDate
+
+class GoalStickerListAdapter(private val eatingType: EatingType, private val cellCount: Int) :
+ ListAdapter(
+ ItemDiffCallback(
+ onContentsTheSame = { old, new -> old == new },
+ onItemsTheSame = { old, new -> old.id == new.id }
+ )
+ ) {
+
+ /** ์ ์ฒด ์
๊ฐ์์์ ์๋ณ ์ผ ์๋ฅผ ๋บ ๋น์นธ ์ */
+ private val blankCellCount: Int = cellCount - LocalDate.now().lengthOfMonth()
+ private lateinit var inflater: LayoutInflater
+
+ class GoalStickerViewHolder(private val binding: ItemGoalStickerBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ fun onBind(data: GoalSticker, eatingType: EatingType, isDefault: Boolean) {
+ binding.layout.setBackgroundColor(eatingType.cardBackgroundColor)
+ if (isDefault)
+ binding.ivSticker.setBackgroundResource(eatingType.defaultStickerRes)
+ else if (data.isDone)
+ binding.ivSticker.setBackgroundResource(eatingType.snailStickerRes)
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GoalStickerViewHolder {
+ if (!::inflater.isInitialized)
+ inflater = LayoutInflater.from(parent.context)
+
+ return GoalStickerViewHolder(ItemGoalStickerBinding.inflate(inflater, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: GoalStickerViewHolder, position: Int) {
+ holder.onBind(currentList[position], eatingType, position >= itemCount - blankCellCount)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/dummy/DummyActivity.kt b/app/src/main/java/org/keepgoeat/presentation/dummy/DummyActivity.kt
deleted file mode 100644
index b706e581..00000000
--- a/app/src/main/java/org/keepgoeat/presentation/dummy/DummyActivity.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.keepgoeat.presentation.dummy
-
-import android.os.Bundle
-import androidx.activity.viewModels
-import dagger.hilt.android.AndroidEntryPoint
-import org.keepgoeat.R
-import org.keepgoeat.databinding.ActivityDummyBinding
-import org.keepgoeat.util.binding.BindingActivity
-
-@AndroidEntryPoint
-class DummyActivity : BindingActivity(R.layout.activity_dummy) {
- private val viewModel: DummyViewModel by viewModels()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding.viewModel = viewModel
-// binding.lifecycleOwner = this // binding์์ LiveData๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ํด๋น ์ฝ๋ ํ์
- }
-
- private fun initLayout() {
- TODO("Not yet implemented")
- }
-
- private fun addListeners() {
- TODO("Not yet implemented")
- }
-
- private fun addObservers() {
- TODO("Not yet implemented")
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/presentation/dummy/DummyViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/dummy/DummyViewModel.kt
deleted file mode 100644
index b1595523..00000000
--- a/app/src/main/java/org/keepgoeat/presentation/dummy/DummyViewModel.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.keepgoeat.presentation.dummy
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.launch
-import org.keepgoeat.domain.repository.DummyRepository
-import javax.inject.Inject
-
-@HiltViewModel
-class DummyViewModel @Inject constructor(private val dummyRepository: DummyRepository) :
- ViewModel() {
- fun uploadDummy() {
- viewModelScope.launch {
- dummyRepository.uploadDummy("keepgoeat", "keepgoeat@gmail.com")
- }
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/presentation/home/HomeActivity.kt b/app/src/main/java/org/keepgoeat/presentation/home/HomeActivity.kt
new file mode 100644
index 00000000..1111409c
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/home/HomeActivity.kt
@@ -0,0 +1,141 @@
+package org.keepgoeat.presentation.home
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityHomeBinding
+import org.keepgoeat.domain.model.HomeGoal
+import org.keepgoeat.presentation.detail.GoalDetailActivity
+import org.keepgoeat.presentation.my.MyActivity
+import org.keepgoeat.presentation.sign.SignActivity
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.presentation.type.ProcessState
+import org.keepgoeat.util.UiState
+import org.keepgoeat.presentation.base.screen.BindingActivity
+
+@AndroidEntryPoint
+class HomeActivity : BindingActivity(R.layout.activity_home) {
+ private val viewModel: HomeViewModel by viewModels()
+ private lateinit var goalAdapter: HomeGoalAdapter
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ if (intent.getBooleanExtra(ARG_KILL_HOME_AND_GO_TO_SIGN, false)) moveToSign()
+
+ viewModel.getForcedUpdateVersion()
+ initLayout()
+ addListeners()
+ collectData()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.startRecodingScreenTime()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ viewModel.stopRecodingScreenTime("$SCREEN_NAME${viewModel.goalCount.value}")
+ }
+
+ private fun addListeners() {
+ with(binding) {
+ btnNoGoal.setOnClickListener {
+ showMakeGoalDialog()
+ }
+ ivMyPage.setOnClickListener {
+ moveToMy()
+ }
+ }
+ }
+
+ private fun initLayout() {
+ goalAdapter =
+ HomeGoalAdapter(::changeGoalItemBtnColor, ::moveToDetail, ::showMakeGoalDialog)
+ binding.rvMyGoals.apply {
+ itemAnimator = null
+ adapter = goalAdapter
+ }
+ }
+
+ private fun collectData() {
+ viewModel.goalList.flowWithLifecycle(lifecycle).onEach { goalList ->
+ goalAdapter.submitList(goalList.toMutableList())
+ }.launchIn(lifecycleScope)
+ viewModel.goalCount.flowWithLifecycle(lifecycle).onEach { goalCount ->
+ if (goalCount > 0)
+ binding.ivHomeSnail.setImageResource(R.drawable.ic_snail_orange_cheer_right)
+ }.launchIn(lifecycleScope)
+ viewModel.lottieState.flowWithLifecycle(lifecycle).onEach { lottieState ->
+ when (lottieState) {
+ ProcessState.IN_PROGRESS -> {
+ binding.lottieSnail.playAnimation()
+ binding.lottieBackground.playAnimation()
+ viewModel.changeLottieState(ProcessState.DONE)
+ }
+ ProcessState.IDLE -> {}
+ ProcessState.DONE -> {}
+ }
+ }.launchIn(lifecycleScope)
+ combine(viewModel.homeDataFetchState, isConnectedNetwork) { fetchState, isConnected ->
+ fetchState !is UiState.Success && isConnected
+ }.flowWithLifecycle(lifecycle).onEach { shouldFetch ->
+ if (shouldFetch) viewModel.fetchHomeContent()
+ }.launchIn(lifecycleScope)
+ viewModel.updateVersion.flowWithLifecycle(lifecycle).onEach { version ->
+ if (viewModel.compareVersion(version)) showForceUpdateDialog(version)
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun showMakeGoalDialog() {
+ HomeBottomDialogFragment().show(supportFragmentManager, "homeDialog")
+ }
+
+ private fun showForceUpdateDialog(updateVersion: String) {
+ HomeForceUpdateDialogFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_UPDATE_VERSION, updateVersion)
+ }
+ }.show(supportFragmentManager, "forceUpdateDialog")
+ }
+
+ private fun moveToDetail(eatingType: EatingType, goalId: Int) {
+ val intent = Intent(this@HomeActivity, GoalDetailActivity::class.java)
+ intent.putExtra(GoalDetailActivity.ARG_EATING_TYPE, eatingType.name)
+ intent.putExtra(GoalDetailActivity.ARG_GOAL_ID, goalId)
+ intent.putExtra(ARG_HOME_GOAL_COUNT, viewModel.goalCount.value)
+ startActivity(intent)
+ }
+
+ private fun moveToMy() {
+ val intent = Intent(this@HomeActivity, MyActivity::class.java)
+ intent.putExtra(ARG_HOME_GOAL_COUNT, viewModel.goalCount.value)
+ startActivity(intent)
+ }
+
+ private fun changeGoalItemBtnColor(myGoal: HomeGoal) {
+ viewModel.changeGoalAchieved(myGoal)
+ }
+
+ private fun moveToSign() {
+ startActivity(Intent(this, SignActivity::class.java))
+ finish()
+ }
+
+ companion object {
+ const val ARG_KILL_HOME_AND_GO_TO_SIGN = "killHomeAndGoToSign"
+ const val ARG_HOME_GOAL_COUNT = "homeGoalCount"
+ const val ARG_UPDATE_VERSION = "updateVersion"
+ const val SCREEN_NAME = "main_goalnum"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/home/HomeBottomDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/home/HomeBottomDialogFragment.kt
new file mode 100644
index 00000000..ff74393d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/home/HomeBottomDialogFragment.kt
@@ -0,0 +1,47 @@
+package org.keepgoeat.presentation.home
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.viewModels
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.R
+import org.keepgoeat.databinding.DialogBottomHomeBinding
+import org.keepgoeat.presentation.base.screen.MixpanelBottomSheetDialogFragment
+import org.keepgoeat.presentation.setting.GoalSettingActivity
+import org.keepgoeat.presentation.type.EatingType
+
+@AndroidEntryPoint
+class HomeBottomDialogFragment :
+ MixpanelBottomSheetDialogFragment(
+ R.layout.dialog_bottom_home, SCREEN_NAME
+ ) {
+ override val viewModel: HomeViewModel by viewModels()
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.layoutHomeBottomMore.setOnClickListener {
+ moveToSetting(EatingType.MORE)
+ viewModel.sendGoalAddEvent(EatingType.MORE)
+ }
+ binding.layoutHomeBottomLess.setOnClickListener {
+ moveToSetting(EatingType.LESS)
+ viewModel.sendGoalAddEvent(EatingType.LESS)
+ }
+ }
+
+ private fun moveToSetting(eatingType: EatingType) {
+ val intent = Intent(requireActivity(), GoalSettingActivity::class.java)
+ intent.putExtra(GoalSettingActivity.ARG_EATING_TYPE, eatingType.name)
+ startActivity(intent)
+ dismiss()
+ }
+
+ companion object {
+ const val SCREEN_NAME = "main_add"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/home/HomeForceUpdateDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/home/HomeForceUpdateDialogFragment.kt
new file mode 100644
index 00000000..d012ec20
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/home/HomeForceUpdateDialogFragment.kt
@@ -0,0 +1,47 @@
+package org.keepgoeat.presentation.home
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.View
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.R
+import org.keepgoeat.databinding.DialogForceUpdateBinding
+import org.keepgoeat.presentation.base.screen.BindingDialogFragment
+
+class HomeForceUpdateDialogFragment :
+ BindingDialogFragment(R.layout.dialog_force_update) {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ isCancelable = false
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.updateVersion = arguments?.getString(ARG_UPDATE_VERSION)
+ binding.currentVersion = BuildConfig.VERSION_NAME
+
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.btnForceUpdate.setOnClickListener {
+ moveToPlayStore()
+ }
+ }
+
+ private fun moveToPlayStore() {
+ Intent(Intent.ACTION_VIEW).apply {
+ data =
+ Uri.parse(getString(R.string.play_store_detail_url) + requireContext().packageName)
+ }.also {
+ startActivity(it)
+ }
+ }
+
+ companion object {
+ const val ARG_UPDATE_VERSION = "updateVersion"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/home/HomeGoalAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/home/HomeGoalAdapter.kt
new file mode 100644
index 00000000..b8f9258f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/home/HomeGoalAdapter.kt
@@ -0,0 +1,153 @@
+package org.keepgoeat.presentation.home
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ItemAddGoalBinding
+import org.keepgoeat.databinding.ItemHomeGoalBinding
+import org.keepgoeat.domain.model.HomeGoal
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.presentation.type.HomeBtnType
+import org.keepgoeat.presentation.type.HomeGoalViewType
+import org.keepgoeat.util.ItemDiffCallback
+import org.keepgoeat.util.extension.setOnSingleClickListener
+import org.keepgoeat.util.setVisibility
+
+class HomeGoalAdapter(
+ private val changeBtnColor: (HomeGoal) -> Unit,
+ private val moveToDetail: (EatingType, Int) -> Unit,
+ private val showMakeGoalDialog: () -> Unit,
+) : ListAdapter(
+ ItemDiffCallback(
+ onContentsTheSame = { old, new -> old == new },
+ onItemsTheSame = { old, new -> old.id == new.id }
+ )
+) {
+ private lateinit var inflater: LayoutInflater
+
+ class MyGoalViewHolder(
+ private val binding: ItemHomeGoalBinding,
+ ) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(
+ myGoal: HomeGoal,
+ eatingType: EatingType,
+ changeBtnColor: (HomeGoal) -> Unit,
+ moveToDetail: (EatingType, Int) -> Unit,
+ ) {
+ val btnType: HomeBtnType = if (eatingType == EatingType.MORE) { // ๋ ๋จน๊ธฐ์ธ ๊ฒฝ์ฐ
+ if (myGoal.isAchieved) {
+ HomeBtnType.PLUS_ACHIEVED
+ } else {
+ HomeBtnType.PLUS_NOT_ACHIEVED
+ }
+ } else { // ๋ ๋จน๊ธฐ์ธ ๊ฒฝ์ฐ
+ if (myGoal.isAchieved) {
+ HomeBtnType.MINUS_ACHIEVED
+ } else {
+ HomeBtnType.MINUS_NOT_ACHIEVED
+ }
+ }
+ binding.goal = myGoal
+ binding.goalType = eatingType
+ binding.goalBtn = btnType
+
+ with(binding) {
+ btnGoalAchieved.setOnSingleClickListener {
+ changeBtnColor(myGoal)
+ }
+ layoutHomeGoal.setOnClickListener {
+ moveToDetail(eatingType, myGoal.id)
+ }
+ }
+ }
+ }
+
+ class AddGoalViewHolder(
+ private val binding: ItemAddGoalBinding,
+ ) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(goalCount: Int, showMakeGoalDialog: () -> Unit) {
+ when (goalCount) {
+ 0 -> binding.layoutGoalInfo.visibility = View.GONE
+ 1 -> binding.tvAddMoreGoal.setText(R.string.home_two_more_goal)
+ 2 -> binding.tvAddMoreGoal.setText(R.string.home_one_more_goal)
+ 3 -> {
+ binding.tvAddMoreGoal.setText(R.string.home_no_more_goal)
+ binding.btnMakeGoal.setVisibility(false)
+ }
+ }
+ if (goalCount < 3) {
+ binding.root.setOnClickListener {
+ showMakeGoalDialog()
+ }
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ if (!::inflater.isInitialized)
+ inflater = LayoutInflater.from(parent.context)
+ return when (viewType) {
+ HomeGoalViewType.MY_GOAL_TYPE.ordinal -> {
+ MyGoalViewHolder(ItemHomeGoalBinding.inflate(inflater, parent, false))
+ }
+ HomeGoalViewType.ADD_GOAL_TYPE.ordinal -> {
+ AddGoalViewHolder(ItemAddGoalBinding.inflate(inflater, parent, false))
+ }
+ else -> {
+ throw java.lang.ClassCastException("Unknown ViewType Error")
+ }
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ when (holder) {
+ is MyGoalViewHolder -> {
+ if (currentList[position].isMore) {
+ holder.bind(
+ currentList[position],
+ EatingType.MORE,
+ changeBtnColor,
+ moveToDetail
+ )
+ } else {
+ holder.bind(
+ currentList[position],
+ EatingType.LESS,
+ changeBtnColor,
+ moveToDetail
+ )
+ }
+ }
+ is AddGoalViewHolder -> holder.bind(currentList.size - 1, showMakeGoalDialog)
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int = currentList[position].type.ordinal
+
+ override fun submitList(list: MutableList?) {
+ if (list != null && list.isNotEmpty()) {
+ if (list.last().type == HomeGoalViewType.ADD_GOAL_TYPE) {
+ super.submitList(list)
+ } else {
+ super.submitList(
+ list.plus(
+ mutableListOf(
+ HomeGoal(
+ 0,
+ "",
+ "",
+ false,
+ false,
+ 0,
+ HomeGoalViewType.ADD_GOAL_TYPE
+ )
+ )
+ )
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/home/HomeViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/home/HomeViewModel.kt
new file mode 100644
index 00000000..482f9288
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/home/HomeViewModel.kt
@@ -0,0 +1,137 @@
+package org.keepgoeat.presentation.home
+
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.domain.model.HomeContent
+import org.keepgoeat.domain.model.HomeGoal
+import org.keepgoeat.domain.repository.GoalRepository
+import org.keepgoeat.domain.repository.VersionRepository
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.presentation.type.ProcessState
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.mixpanel.GoalEvent
+import timber.log.Timber
+import java.io.IOException
+import java.time.LocalDateTime
+import javax.inject.Inject
+
+@HiltViewModel
+class HomeViewModel @Inject constructor(
+ private val goalRepository: GoalRepository,
+ private val versionRepository: VersionRepository,
+) : MixpanelViewModel() {
+ private val _homeDataFetchState = MutableStateFlow>(UiState.Loading)
+ val homeDataFetchState get() = _homeDataFetchState.asStateFlow()
+ private var _goalList = MutableStateFlow>(mutableListOf())
+ val goalList get() = _goalList.asStateFlow()
+ private val _goalCount = MutableStateFlow(0)
+ val goalCount = _goalCount.asStateFlow()
+ private val _hour = MutableStateFlow(LocalDateTime.now().hour)
+ val hour = _hour.asStateFlow()
+ private val _cheeringMessage = MutableStateFlow("")
+ val cheeringMessage = _cheeringMessage.asStateFlow()
+ private val _lottieState = MutableStateFlow(ProcessState.IDLE)
+ val lottieState get() = _lottieState.asStateFlow()
+ private val _updateVersion = MutableStateFlow("")
+ val updateVersion get() = _updateVersion.asStateFlow()
+
+ fun fetchHomeContent() {
+ viewModelScope.launch {
+ goalRepository.fetchHomeContent()
+ .onSuccess { homeContent ->
+ _homeDataFetchState.value = UiState.Success(homeContent)
+ _goalList.value = homeContent.goals.toMutableList()
+ _cheeringMessage.value = homeContent.cheeringMessage
+ _lottieState.value = ProcessState.IDLE
+ _goalCount.value = homeContent.goals.size
+ }.onFailure { throwable ->
+ when (throwable) {
+ is IOException ->
+ _homeDataFetchState.value = UiState.Error(throwable.message)
+ }
+ Timber.e(throwable.message)
+ }
+ }
+ }
+
+ fun changeGoalAchieved(goal: HomeGoal) {
+ val position = goalList.value.indexOf(goal)
+ viewModelScope.launch {
+ goalRepository.achieveGoal(goal.id, !goal.isAchieved)
+ .onSuccess { goalData ->
+ val list = _goalList.value.toMutableList()
+ with(goal) {
+ list.set(
+ position,
+ HomeGoal(
+ id,
+ goalTitle,
+ goalCriterion,
+ isMore,
+ goalData.updatedIsAchieved,
+ goalData.thisMonthCount,
+ type
+ )
+ )
+ }
+ if (goalData.updatedIsAchieved) {
+ _lottieState.value = ProcessState.IN_PROGRESS
+ mixpanelProvider.sendEvent(
+ GoalEvent.completeGoal(
+ goal.goalTitle,
+ goal.goalCriterion
+ ),
+ true
+ )
+ }
+ _goalList.value =
+ list.toMutableList()
+ }
+ .onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+
+ fun changeLottieState(state: ProcessState) {
+ _lottieState.value = state
+ }
+
+ fun sendGoalAddEvent(eatingType: EatingType) {
+ val goalType = if (eatingType == EatingType.MORE) "๋๋จน๊ธฐ" else "๋๋จน๊ธฐ"
+ mixpanelProvider.sendEvent(GoalEvent.addGoal(goalType), false)
+ }
+
+ fun getForcedUpdateVersion() {
+ viewModelScope.launch {
+ versionRepository.getForcedUpdateVersion(CLIENT_TYPE)
+ .onSuccess {
+ _updateVersion.value = it.version
+ }
+ .onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+
+ fun compareVersion(updateVersion: String): Boolean {
+ if (updateVersion.isBlank()) return false
+
+ val splitCurrent = BuildConfig.VERSION_NAME.split(".")
+ val splitUpdate = updateVersion.split(".")
+ if (splitCurrent.size > 2 && splitUpdate.size > 2) {
+ if (splitCurrent[2] != splitUpdate[2]) return true
+ }
+
+ return false
+ }
+
+ companion object {
+ private const val CLIENT_TYPE = "AOS"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/model/GoalContent.kt b/app/src/main/java/org/keepgoeat/presentation/model/GoalContent.kt
new file mode 100644
index 00000000..d83670c8
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/model/GoalContent.kt
@@ -0,0 +1,11 @@
+package org.keepgoeat.presentation.model
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class GoalContent(
+ val id: Int,
+ val food: String,
+ val criterion: String
+) : Parcelable
diff --git a/app/src/main/java/org/keepgoeat/presentation/model/MixPanelEvent.kt b/app/src/main/java/org/keepgoeat/presentation/model/MixPanelEvent.kt
new file mode 100644
index 00000000..3c08cc1c
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/model/MixPanelEvent.kt
@@ -0,0 +1,6 @@
+package org.keepgoeat.presentation.model
+
+data class MixPanelEvent(
+ val name: String,
+ val params: Map?
+)
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/AccountInfoActivity.kt b/app/src/main/java/org/keepgoeat/presentation/my/AccountInfoActivity.kt
new file mode 100644
index 00000000..500e4998
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/AccountInfoActivity.kt
@@ -0,0 +1,91 @@
+package org.keepgoeat.presentation.my
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.data.service.KakaoAuthService
+import org.keepgoeat.data.service.NaverAuthService
+import org.keepgoeat.databinding.ActivityAccountInfoBinding
+import org.keepgoeat.domain.model.UserInfo
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.home.HomeActivity.Companion.ARG_KILL_HOME_AND_GO_TO_SIGN
+import org.keepgoeat.presentation.my.MyActivity.Companion.ARG_USER_INFO
+import org.keepgoeat.presentation.my.withdraw.WithdrawActivity
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.getParcelable
+import org.keepgoeat.util.extension.showToast
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class AccountInfoActivity :
+ MixpanelActivity(R.layout.activity_account_info, SCREEN_NAME) {
+ @Inject
+ lateinit var kakaoSignService: KakaoAuthService
+
+ @Inject
+ lateinit var naverSignService: NaverAuthService
+ override val viewModel: MyViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ intent.getParcelable(ARG_USER_INFO, UserInfo::class.java)?.let { // TODO need refactoring
+ binding.tvUserName.text = it.name
+ binding.tvUserEmail.text = it.email
+ }
+
+ addListeners()
+ collectData()
+ }
+
+ private fun addListeners() {
+ binding.viewToolbar.ivBack.setOnClickListener {
+ finish()
+ }
+ binding.tvLogout.setOnClickListener {
+ LogoutDialogFragment().show(supportFragmentManager, "logoutDialog")
+ }
+ binding.tvDeleteAccount.setOnClickListener {
+ val intent = Intent(this, WithdrawActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+ startActivity(intent)
+ }
+ }
+
+ private fun collectData() {
+ viewModel.logoutUiState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> {
+ showToast(getString(R.string.my_logout_success_toast_message))
+ moveToSign()
+ }
+ is UiState.Error -> {
+ showToast(getString(R.string.my_logout_failure_toast_message))
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun moveToSign() {
+ Intent(this, HomeActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+ putExtra(ARG_KILL_HOME_AND_GO_TO_SIGN, true)
+ }.also {
+ startActivity(it)
+ }
+ }
+
+ companion object {
+ private const val SCREEN_NAME = "account"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/LogoutDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/my/LogoutDialogFragment.kt
new file mode 100644
index 00000000..25791330
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/LogoutDialogFragment.kt
@@ -0,0 +1,47 @@
+package org.keepgoeat.presentation.my
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.R
+import org.keepgoeat.data.service.KakaoAuthService
+import org.keepgoeat.data.service.NaverAuthService
+import org.keepgoeat.databinding.DialogLogoutBinding
+import org.keepgoeat.presentation.type.LoginPlatformType
+import org.keepgoeat.presentation.base.screen.BindingDialogFragment
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class LogoutDialogFragment : BindingDialogFragment(R.layout.dialog_logout) {
+ @Inject
+ lateinit var kakaoSignService: KakaoAuthService
+
+ @Inject
+ lateinit var naverSignService: NaverAuthService
+
+ private val viewModel: MyViewModel by activityViewModels()
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = viewLifecycleOwner
+
+ addListeners()
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.yes.setOnClickListener {
+ when (viewModel.loginPlatForm) {
+ LoginPlatformType.NAVER -> naverSignService.logoutNaver(viewModel::logout)
+ LoginPlatformType.KAKAO -> kakaoSignService.logoutKakao(viewModel::logout)
+ else -> {}
+ }
+ dismiss()
+ }
+ binding.no.setOnClickListener {
+ dismiss()
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/MyActivity.kt b/app/src/main/java/org/keepgoeat/presentation/my/MyActivity.kt
new file mode 100644
index 00000000..8e3b98d9
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/MyActivity.kt
@@ -0,0 +1,125 @@
+package org.keepgoeat.presentation.my
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import androidx.activity.viewModels
+import com.google.android.play.core.review.ReviewManagerFactory
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityMyBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.common.WebViewActivity
+import org.keepgoeat.presentation.my.archive.ArchivedGoalActivity
+import org.keepgoeat.util.extension.showToast
+
+@AndroidEntryPoint
+class MyActivity : MixpanelActivity(R.layout.activity_my, SCREEN_NAME) {
+ override val viewModel: MyViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ viewModel.fetchUserInfo()
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.viewToolbar.ivBack.setOnClickListener {
+ finish()
+ }
+ binding.tvUserName.setOnClickListener {
+ Intent(this, AccountInfoActivity::class.java).apply {
+ putExtra(ARG_USER_INFO, viewModel.userInfo.value)
+ }.also {
+ startActivity(it)
+ }
+ }
+ binding.layoutArchivedGoal.setOnClickListener {
+ moveToArchivedGoalDetail()
+ }
+ binding.tvContactUs.setOnClickListener {
+ sendMail(
+ getString(R.string.my_contact_us_mail_title),
+ String.format(
+ getString(R.string.my_contact_us_mail_content),
+ Build.BRAND,
+ Build.DEVICE,
+ BuildConfig.VERSION_NAME,
+ Build.VERSION.SDK_INT,
+ Build.VERSION.RELEASE
+ )
+ )
+ }
+ binding.tvFeedback.setOnClickListener {
+ moveToPlayStore()
+ }
+ binding.tvAboutService.setOnClickListener {
+ startActivity(Intent(this, ServiceIntroActivity::class.java))
+ }
+ binding.tvTerms.setOnClickListener {
+ moveToWebPage(TERMS_LINK)
+ }
+ binding.tvPolicy.setOnClickListener {
+ moveToWebPage(POLICY_LINK)
+ }
+ }
+
+ private fun moveToArchivedGoalDetail() {
+ val homeGoalCount = intent.getIntExtra(ARG_HOME_GOAL_COUNT, -1)
+ val intent = Intent(this, ArchivedGoalActivity::class.java)
+ intent.putExtra(ARG_HOME_GOAL_COUNT, homeGoalCount)
+ startActivity(intent)
+ }
+
+ private fun sendMail(title: String, content: String) {
+ Intent(Intent.ACTION_SEND).apply {
+ type = "plain/text"
+ putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.keep_go_eat_mail)))
+ putExtra(Intent.EXTRA_SUBJECT, title)
+ putExtra(Intent.EXTRA_TEXT, content)
+ }.also { startActivity(it) }
+ }
+
+ private fun showReviewDialog() {
+ val manager = ReviewManagerFactory.create(this)
+ manager.requestReviewFlow().addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ manager.launchReviewFlow(this, task.result)
+ .addOnCompleteListener {
+ showToast(getString(R.string.my_feedback_success_toast_message))
+ }
+ } else {
+ moveToPlayStore()
+ }
+ }
+ }
+
+ private fun moveToWebPage(link: String) {
+ Intent(this, WebViewActivity::class.java).apply {
+ putExtra(WebViewActivity.ARG_WEB_VIEW_LINK, link)
+ }.also { startActivity(it) }
+ }
+
+ private fun moveToPlayStore() {
+ Intent(Intent.ACTION_VIEW).apply {
+ data = Uri.parse(getString(R.string.play_store_detail_url) + packageName)
+ }.also {
+ startActivity(it)
+ }
+ }
+
+ companion object {
+ private const val TERMS_LINK =
+ "https://68space.notion.site/7d49b1a8912440cb9ec262392e5583e2"
+ private const val POLICY_LINK =
+ "https://68space.notion.site/9083a018baab42958103596378417c13"
+ const val ARG_HOME_GOAL_COUNT = "homeGoalCount"
+ const val ARG_USER_INFO = "userInfo"
+ private const val SCREEN_NAME = "mypage"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/MyViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/my/MyViewModel.kt
new file mode 100644
index 00000000..5bef7ff3
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/MyViewModel.kt
@@ -0,0 +1,154 @@
+package org.keepgoeat.presentation.my
+
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.domain.model.ArchivedGoal
+import org.keepgoeat.domain.model.UserInfo
+import org.keepgoeat.domain.repository.AuthRepository
+import org.keepgoeat.domain.repository.GoalRepository
+import org.keepgoeat.domain.repository.UserRepository
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.presentation.type.WithdrawReason
+import org.keepgoeat.presentation.type.SortType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.toStateFlow
+import org.keepgoeat.util.mixpanel.SignEvent
+import timber.log.Timber
+import javax.inject.Inject
+
+@HiltViewModel
+class MyViewModel @Inject constructor(
+ // TODO need refactoring
+ private val authRepository: AuthRepository,
+ private val goalRepository: GoalRepository,
+ private val userRepository: UserRepository,
+ private val localStorage: KGEDataSource,
+) : MixpanelViewModel() {
+ private val _userInfo = MutableStateFlow(UserInfo("", "", 0))
+ val userInfo get() = _userInfo.asStateFlow()
+
+ private val _archivedGoalFetchUiState =
+ MutableStateFlow>>(UiState.Loading)
+ val archivedGoalFetchUiState get() = _archivedGoalFetchUiState.asStateFlow()
+ private val _archivedGoalCount = MutableStateFlow(0)
+ private val _allArchivedGoalCount = MutableStateFlow(0)
+
+ private val _logoutUiState = MutableStateFlow>(UiState.Loading)
+ val logoutUiState get() = _logoutUiState.asStateFlow()
+
+ private val _goalDeleteState = MutableStateFlow>(UiState.Loading)
+ val goalDeleteState get() = _goalDeleteState.asStateFlow()
+ private var _deletedGoalCount = 0
+ val deletedGoalCount get() = _deletedGoalCount
+
+ val archivedGoalCount get() = _archivedGoalCount.asStateFlow()
+ val allArchivedGoalCount get() = _allArchivedGoalCount.asStateFlow()
+
+ private val _deleteAccountUiState =
+ MutableStateFlow>(UiState.Loading)
+ val deleteAccountUiState get() = _deleteAccountUiState.asStateFlow()
+ val otherReason = MutableStateFlow("")
+ val isValidOtherReason: StateFlow
+ get() = otherReason.map { reason ->
+ reason.isNotBlank()
+ }.toStateFlow(viewModelScope, false)
+ private val _isKeyboardVisible = MutableStateFlow(false)
+ val isKeyboardVisible get() = _isKeyboardVisible.asStateFlow()
+ private val _isOtherReasonSelected = MutableStateFlow(false)
+ val isOtherReasonSelected get() = _isOtherReasonSelected.asStateFlow()
+ private val _selectedReasons: MutableStateFlow> =
+ MutableStateFlow(arrayListOf())
+ private val selectedReasons get() = _selectedReasons.asStateFlow()
+ val loginPlatForm = localStorage.loginPlatform
+
+ fun fetchUserInfo() {
+ viewModelScope.launch {
+ userRepository.fetchUserInfo().onSuccess { userInfo ->
+ userInfo?.let {
+ _userInfo.value = userInfo
+ }
+ }
+ }
+ }
+
+ fun fetchArchivedGoalBySort(sortType: SortType) {
+ viewModelScope.launch {
+ goalRepository.fetchArchivedGoal(sortType.name.lowercase())
+ .onSuccess {
+ _archivedGoalFetchUiState.value = UiState.Success(it)
+ _archivedGoalCount.value = it.size
+ if (sortType == SortType.ALL)
+ _allArchivedGoalCount.value = it.size
+ }.onFailure {
+ _archivedGoalFetchUiState.value = UiState.Error(null)
+ }
+ }
+ }
+
+ fun deleteArchivedGoal(id: Int) {
+ viewModelScope.launch {
+ goalRepository.deleteGoal(id).onSuccess { deletedData ->
+ _goalDeleteState.value = UiState.Success(deletedData.goalId)
+ _archivedGoalCount.value -= 1
+ _allArchivedGoalCount.value -= 1
+ _deletedGoalCount += 1 // TODO need refactoring
+ }.onFailure {
+ Timber.e(it.message)
+ }
+ }
+ }
+
+ fun logout() {
+ localStorage.clear()
+ _logoutUiState.value = UiState.Success(true)
+ }
+
+ fun deleteAccount() {
+ viewModelScope.launch {
+ authRepository.deleteAccount()
+ .onSuccess {
+ _deleteAccountUiState.value = UiState.Success(true)
+ }.onFailure {
+ _deleteAccountUiState.value = UiState.Error(it.message)
+ }
+ }
+ }
+
+ fun setKeyboardVisibility(visible: Boolean) {
+ _isKeyboardVisible.value = visible
+ }
+
+ fun onCheckBoxClick() {
+ _isOtherReasonSelected.value = !isOtherReasonSelected.value
+ }
+
+ fun changeCheckboxSelected(isSelected: Boolean) {
+ _isOtherReasonSelected.value = isSelected
+ }
+
+ fun selectReasons(isSelected: WithdrawReason) {
+ if (_selectedReasons.value.contains(isSelected)) {
+ _selectedReasons.value.remove(isSelected)
+ return
+ }
+ _selectedReasons.value.add(isSelected)
+ }
+
+ fun sendDeleteAccountEvent(reasons: Map?) {
+ mixpanelProvider.sendEvent(SignEvent.deleteAccount(reasons))
+ }
+
+ fun getWithdrawReasons(): MutableMap {
+ val reasons: MutableMap =
+ selectedReasons.value.associate { it.name to it.reason }.toMutableMap()
+ if (isOtherReasonSelected.value)
+ reasons["SUBJECTIVE_ISSUE"] = otherReason.value
+ return reasons
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/ServiceIntroActivity.kt b/app/src/main/java/org/keepgoeat/presentation/my/ServiceIntroActivity.kt
new file mode 100644
index 00000000..356d1268
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/ServiceIntroActivity.kt
@@ -0,0 +1,44 @@
+package org.keepgoeat.presentation.my
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityServiceIntroBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.common.WebViewActivity
+import org.keepgoeat.presentation.common.WebViewActivity.Companion.ARG_WEB_VIEW_LINK
+
+@AndroidEntryPoint
+class ServiceIntroActivity :
+ MixpanelActivity(R.layout.activity_service_intro, SCREEN_NAME) {
+ override val viewModel: MyViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.viewToolbar.ivBack.setOnClickListener {
+ finish()
+ }
+ binding.tvOpenSource.setOnClickListener {
+ moveToOpenSourcePage()
+ }
+ }
+
+ private fun moveToOpenSourcePage() {
+ Intent(this, WebViewActivity::class.java).apply {
+ putExtra(ARG_WEB_VIEW_LINK, OPEN_SOURCE_LINK)
+ }.also { startActivity(it) }
+ }
+
+ companion object {
+ private const val OPEN_SOURCE_LINK =
+ "https://68space.notion.site/cd16c9399dfe4c7a867deb59851282e3"
+ private const val SCREEN_NAME = "service intro"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalActivity.kt b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalActivity.kt
new file mode 100644
index 00000000..1372d61b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalActivity.kt
@@ -0,0 +1,154 @@
+package org.keepgoeat.presentation.my.archive
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.MotionEvent
+import android.view.View
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.ConcatAdapter
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityArchivedGoalBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.my.MyActivity
+import org.keepgoeat.presentation.my.MyViewModel
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.presentation.type.SortType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.showToast
+
+@AndroidEntryPoint
+class ArchivedGoalActivity :
+ MixpanelActivity(R.layout.activity_archived_goal, SCREEN_NAME) {
+ override val viewModel: MyViewModel by viewModels()
+ lateinit var goalAdapter: ArchivedGoalAdapter
+ private val headerAdapter = ArchivedGoalHeaderAdapter(::getFilteredGoalWithEatingType)
+ lateinit var goalConcatAdapter: ConcatAdapter
+ private var isEnteredFromKeep: Boolean = false
+
+ private val callback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ moveToPrevious()
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+ isEnteredFromKeep = intent.getBooleanExtra(ARG_IS_ENTERED_FROM_KEEP, false)
+
+ viewModel.fetchArchivedGoalBySort(SortType.ALL)
+ goalAdapter = ArchivedGoalAdapter(::showKeepDeleteDialog)
+ goalConcatAdapter = ConcatAdapter(headerAdapter, goalAdapter)
+
+ initLayout()
+ addListeners()
+ collectData()
+ }
+
+ override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
+ goalAdapter.checkForVisibleDeleteButton()
+ return super.dispatchTouchEvent(ev)
+ }
+
+ private fun initLayout() {
+ binding.rvGoalList.apply {
+ adapter = goalConcatAdapter
+ itemAnimator = null
+ }
+ this.onBackPressedDispatcher.addCallback(this, callback)
+ }
+
+ private fun getFilteredGoalWithEatingType(eatingType: EatingType?) {
+ when (eatingType) {
+ null -> viewModel.fetchArchivedGoalBySort(SortType.ALL)
+ EatingType.MORE -> viewModel.fetchArchivedGoalBySort(SortType.MORE)
+ EatingType.LESS -> viewModel.fetchArchivedGoalBySort(SortType.LESS)
+ }
+ }
+
+ private fun addListeners() {
+ binding.viewToolbar.ivBack.setOnClickListener {
+ moveToPrevious()
+ }
+ binding.btnMoreKeep.setOnClickListener {
+ moveToHome()
+ }
+ }
+
+ private fun collectData() {
+ viewModel.archivedGoalFetchUiState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> {
+ goalAdapter.setGoalList(it.data.toMutableList())
+ }
+ is UiState.Error -> {}
+ is UiState.Loading -> {}
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+
+ viewModel.goalDeleteState.flowWithLifecycle(lifecycle).onEach { deleteState ->
+ when (deleteState) {
+ is UiState.Success -> {
+ goalAdapter.removeGoal(deleteState.data)
+ showToast(getString(R.string.goal_detail_success_goal_delete_toast_message))
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+
+ viewModel.allArchivedGoalCount.flowWithLifecycle(lifecycle).onEach { allAchievedGoalCount ->
+ val homeGoalCount = intent.getIntExtra(ARG_HOME_GOAL_COUNT, -1)
+ if (homeGoalCount == 0 && allAchievedGoalCount == 0) {
+ binding.btnMoreKeep.visibility = View.VISIBLE
+ } else {
+ binding.btnMoreKeep.visibility = View.INVISIBLE
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun moveToHome() {
+ val intent = Intent(this, HomeActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivity(intent)
+ }
+
+ private fun moveToMy() {
+ if (viewModel.deletedGoalCount > 0)
+ Intent(this, MyActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+ }.also {
+ startActivity(it)
+ }
+ else
+ finish()
+ }
+
+ private fun moveToPrevious() {
+ if (isEnteredFromKeep) moveToHome()
+ else moveToMy()
+ }
+
+ private fun showKeepDeleteDialog(goalId: Int) {
+ GoalDeleteDialogFragment().apply {
+ arguments = Bundle().apply {
+ putInt(ARG_GOAL_ID, goalId)
+ }
+ }.show(supportFragmentManager, "archivedGoalDeleteDialog")
+ }
+
+ companion object {
+ const val ARG_IS_ENTERED_FROM_KEEP = "isEnteredFromKeep"
+ const val ARG_GOAL_ID = "goalId"
+ const val ARG_HOME_GOAL_COUNT = "homeGoalCount"
+ const val SCREEN_NAME = "archived goal"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalAdapter.kt
new file mode 100644
index 00000000..010506f2
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalAdapter.kt
@@ -0,0 +1,84 @@
+package org.keepgoeat.presentation.my.archive
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.databinding.ItemArchivedGoalBinding
+import org.keepgoeat.domain.model.ArchivedGoal
+
+class ArchivedGoalAdapter(
+ private val showKeepDeleteDialog: (Int) -> Unit,
+) : RecyclerView.Adapter() {
+ private lateinit var inflater: LayoutInflater
+ private val goalLists: MutableList = mutableListOf()
+ private var goalWithDeleteViewVisible: ArchivedGoal? = null
+
+ class ArchivedGoalViewHolder(private val binding: ItemArchivedGoalBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ fun onBind(
+ data: ArchivedGoal,
+ showKeepDeleteDialog: (Int) -> Unit,
+ showDeleteButton: (Button, ArchivedGoal) -> Unit,
+ hideDeleteButton: (Button) -> Unit,
+ ) {
+ binding.goal = data
+
+ if (binding.btnArchivedGoalDelete.visibility == View.VISIBLE)
+ hideDeleteButton(binding.btnArchivedGoalDelete)
+
+ binding.ivArchivedGoalDetail.setOnClickListener {
+ if (binding.btnArchivedGoalDelete.visibility == View.INVISIBLE)
+ showDeleteButton(binding.btnArchivedGoalDelete, data)
+ }
+ binding.btnArchivedGoalDelete.setOnClickListener {
+ showKeepDeleteDialog(data.id)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArchivedGoalViewHolder {
+ if (!::inflater.isInitialized)
+ inflater = LayoutInflater.from(parent.context)
+
+ return ArchivedGoalViewHolder(ItemArchivedGoalBinding.inflate(inflater, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ArchivedGoalViewHolder, position: Int) {
+ holder.onBind(
+ goalLists[position],
+ showKeepDeleteDialog,
+ ::showDeleteButton,
+ ::hideDeleteButton
+ )
+ }
+
+ override fun getItemCount() = goalLists.size
+
+ fun setGoalList(goals: MutableList) {
+ goalLists.clear()
+ goalLists.addAll(goals)
+ notifyDataSetChanged()
+ }
+
+ private fun hideDeleteButton(deleteButton: Button) {
+ deleteButton.visibility = View.INVISIBLE
+ goalWithDeleteViewVisible = null
+ }
+
+ private fun showDeleteButton(deleteButton: Button, goal: ArchivedGoal) {
+ deleteButton.visibility = View.VISIBLE
+ goalWithDeleteViewVisible = goal
+ }
+
+ fun checkForVisibleDeleteButton() {
+ if (goalWithDeleteViewVisible == null) return
+ else notifyItemChanged(goalLists.indexOf(goalWithDeleteViewVisible))
+ }
+
+ fun removeGoal(goalId: Int) {
+ val goal = goalLists.find { it.id == goalId }
+ notifyItemRemoved(goalLists.indexOf(goal))
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalHeaderAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalHeaderAdapter.kt
new file mode 100644
index 00000000..8bb48a7f
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/archive/ArchivedGoalHeaderAdapter.kt
@@ -0,0 +1,69 @@
+package org.keepgoeat.presentation.my.archive
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.R
+import org.keepgoeat.databinding.LayoutArchivedGoalHeaderBinding
+import org.keepgoeat.presentation.type.EatingType
+
+class ArchivedGoalHeaderAdapter(private val eatingTypeClickListener: ((EatingType?) -> Unit)) :
+ RecyclerView.Adapter() {
+ private lateinit var inflater: LayoutInflater
+
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int,
+ ): ArchivedGoalHeaderViewHolder {
+ if (!::inflater.isInitialized)
+ inflater = LayoutInflater.from(parent.context)
+
+ return ArchivedGoalHeaderViewHolder(
+ LayoutArchivedGoalHeaderBinding.inflate(inflater, parent, false)
+ )
+ }
+
+ override fun onBindViewHolder(holder: ArchivedGoalHeaderViewHolder, position: Int) {
+ holder.onBind(eatingTypeClickListener, ::changeTextAppearance)
+ }
+
+ override fun getItemCount() = 1
+
+ private fun changeTextAppearance(
+ clickedView: TextView,
+ unclickedView1: TextView,
+ unclickedView2: TextView,
+ ) {
+ clickedView.setTextAppearance(R.style.TextAppearance_System5_Bold)
+ unclickedView1.setTextAppearance(R.style.TextAppearance_System5)
+ unclickedView2.setTextAppearance(R.style.TextAppearance_System5)
+ clickedView.setTextColor(clickedView.context.getColor(R.color.gray_800))
+ unclickedView1.setTextColor(clickedView.context.getColor(R.color.gray_400))
+ unclickedView2.setTextColor(clickedView.context.getColor(R.color.gray_400))
+ }
+
+ class ArchivedGoalHeaderViewHolder(
+ private val binding: LayoutArchivedGoalHeaderBinding,
+ ) : RecyclerView.ViewHolder(binding.root) {
+ fun onBind(
+ eatingTypeClickListener: ((EatingType?) -> Unit),
+ changeTextAppearance: (TextView, TextView, TextView) -> Unit,
+ ) {
+ with(binding) {
+ tvAll.setOnClickListener {
+ eatingTypeClickListener(null)
+ changeTextAppearance(tvAll, tvMore, tvLess)
+ }
+ tvMore.setOnClickListener {
+ eatingTypeClickListener(EatingType.MORE)
+ changeTextAppearance(tvMore, tvAll, tvLess)
+ }
+ tvLess.setOnClickListener {
+ eatingTypeClickListener(EatingType.LESS)
+ changeTextAppearance(tvLess, tvAll, tvMore)
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/archive/GoalDeleteDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/my/archive/GoalDeleteDialogFragment.kt
new file mode 100644
index 00000000..55df0eff
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/archive/GoalDeleteDialogFragment.kt
@@ -0,0 +1,42 @@
+package org.keepgoeat.presentation.my.archive
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import org.keepgoeat.R
+import org.keepgoeat.databinding.DialogGoalDeleteBinding
+import org.keepgoeat.presentation.my.MyViewModel
+import org.keepgoeat.presentation.base.screen.BindingDialogFragment
+
+class GoalDeleteDialogFragment :
+ BindingDialogFragment(R.layout.dialog_goal_delete) {
+ private val viewModel: MyViewModel by activityViewModels()
+ private var goalId: Int? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ goalId = arguments?.getInt(ARG_GOAL_ID)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.viewModel = viewModel
+ addListeners()
+ }
+
+ private fun addListeners() {
+ binding.no.setOnClickListener {
+ dismiss()
+ }
+ binding.yes.setOnClickListener {
+ goalId?.let { goalId ->
+ viewModel.deleteArchivedGoal(goalId)
+ }
+ dismiss()
+ }
+ }
+
+ companion object {
+ const val ARG_GOAL_ID = "goalId"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawActivity.kt b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawActivity.kt
new file mode 100644
index 00000000..45e01145
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawActivity.kt
@@ -0,0 +1,143 @@
+package org.keepgoeat.presentation.my.withdraw
+
+import android.graphics.Rect
+import android.os.Bundle
+import android.view.View
+import android.view.ViewTreeObserver
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityWithdrawBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.my.MyViewModel
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.showKeyboard
+import org.keepgoeat.util.setVisibility
+
+@AndroidEntryPoint
+class WithdrawActivity :
+ MixpanelActivity(R.layout.activity_withdraw, SCREEN_NAME) {
+ override val viewModel: MyViewModel by viewModels()
+ lateinit var onGlobalListener: ViewTreeObserver.OnGlobalLayoutListener
+ lateinit var rootView: View
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+ rootView = binding.root
+
+ initLayout()
+ addListeners()
+ collectData()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ rootView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ rootView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener)
+ }
+
+ private fun initLayout() {
+ binding.rvWithdraw.apply {
+ itemAnimator = null
+ adapter = WithdrawReasonAdapter(viewModel::selectReasons)
+ }
+
+ initGlobalListener()
+ }
+
+ private fun initGlobalListener() {
+ onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
+ val rect = Rect()
+ rootView.getWindowVisibleDisplayFrame(rect)
+ val screenHeight = rootView.rootView.height
+ val keypadHeight = screenHeight - rect.bottom
+ viewModel.setKeyboardVisibility(keypadHeight > screenHeight * 0.15)
+ }
+ }
+
+ private fun addListeners() {
+ binding.etOtherReason.setOnFocusChangeListener { _, focused ->
+ if (focused) { // '์ง์ ์
๋ ฅ' editText๊ฐ focus ์ํ์ผ ๋
+ requestFocus()
+ viewModel.changeCheckboxSelected(true)
+ } else {
+ clearFocus()
+ }
+ }
+ binding.layoutWithdraw.setOnClickListener { // ์ธ๋ถ ์์ญ ํด๋ฆญ ํ์ ๋
+ clearFocus()
+ }
+ binding.btnWithdraw.setOnClickListener {
+ if (binding.etOtherReason.text.isNullOrBlank() && viewModel.isOtherReasonSelected.value)
+ binding.tvOtherReasonErrorMsg.setVisibility(true)
+ else
+ WithdrawDialogFragment().show(
+ supportFragmentManager,
+ "withdrawDialog"
+ )
+ }
+ binding.viewWithdrawToolbar.ivBack.setOnClickListener {
+ finish()
+ }
+ }
+
+ private fun collectData() {
+ viewModel.isOtherReasonSelected.flowWithLifecycle(lifecycle).onEach { isSelected ->
+ if (isSelected) {
+ requestFocus()
+ } else {
+ clearFocus()
+ }
+ }.launchIn(lifecycleScope)
+ viewModel.isValidOtherReason.flowWithLifecycle(lifecycle).onEach { isValid ->
+ if (isValid)
+ binding.tvOtherReasonErrorMsg.setVisibility(false)
+ }.launchIn(lifecycleScope)
+ viewModel.isKeyboardVisible.flowWithLifecycle(lifecycle).onEach { isVisible ->
+ binding.rvWithdraw.setVisibility(!isVisible)
+ }.launchIn(lifecycleScope)
+ viewModel.deleteAccountUiState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> sendDeleteAccountEvent()
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun sendDeleteAccountEvent() {
+ val reasons: MutableMap = mutableMapOf()
+ viewModel.getWithdrawReasons().map {
+ if (it.key == SUBJECTIVE_ISSUE) {
+ reasons[it.key] = it.value
+ } else {
+ reasons[it.key] = (it.value as? Int)?.let { value -> getString(value) } ?: ""
+ }
+ }
+ viewModel.sendDeleteAccountEvent(reasons)
+ }
+
+ private fun clearFocus() {
+ binding.etOtherReason.clearFocus()
+ showKeyboard(binding.etOtherReason, false)
+ }
+
+ private fun requestFocus() {
+ binding.etOtherReason.requestFocus()
+ showKeyboard(binding.etOtherReason, true)
+ }
+
+ companion object {
+ private const val SUBJECTIVE_ISSUE = "SUBJECTIVE_ISSUE"
+ private const val SCREEN_NAME = "account_delete"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawDialogFragment.kt b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawDialogFragment.kt
new file mode 100644
index 00000000..717700c9
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawDialogFragment.kt
@@ -0,0 +1,78 @@
+package org.keepgoeat.presentation.my.withdraw
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.data.service.KakaoAuthService
+import org.keepgoeat.data.service.NaverAuthService
+import org.keepgoeat.databinding.DialogWithdrawBinding
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.my.MyViewModel
+import org.keepgoeat.presentation.type.LoginPlatformType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.presentation.base.screen.BindingDialogFragment
+import org.keepgoeat.util.extension.showToast
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class WithdrawDialogFragment :
+ BindingDialogFragment(R.layout.dialog_withdraw) {
+ @Inject
+ lateinit var kakaoSignService: KakaoAuthService
+
+ @Inject
+ lateinit var naverSignService: NaverAuthService
+ private val viewModel: MyViewModel by activityViewModels()
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ addListeners()
+ collectData()
+ }
+
+ private fun addListeners() {
+ binding.tvCancel.setOnClickListener {
+ dismiss()
+ }
+ binding.tvWithdraw.setOnClickListener {
+ when (viewModel.loginPlatForm) {
+ LoginPlatformType.NAVER -> naverSignService.deleteAccountNaver(viewModel::deleteAccount)
+ LoginPlatformType.KAKAO -> kakaoSignService.deleteAccountKakao(viewModel::deleteAccount)
+ else -> {}
+ }
+ }
+ }
+
+ private fun collectData() {
+ viewModel.deleteAccountUiState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> {
+ requireActivity().showToast(getString(R.string.withdraw_success))
+ moveToSign()
+ dismiss()
+ }
+ is UiState.Error -> {
+ requireActivity().showToast(getString(R.string.withdraw_fail))
+ dismiss()
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun moveToSign() {
+ Intent(context, HomeActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+ putExtra(HomeActivity.ARG_KILL_HOME_AND_GO_TO_SIGN, true)
+ }.also {
+ startActivity(it)
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawReasonAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawReasonAdapter.kt
new file mode 100644
index 00000000..5032dda8
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/my/withdraw/WithdrawReasonAdapter.kt
@@ -0,0 +1,52 @@
+package org.keepgoeat.presentation.my.withdraw
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.databinding.ItemWithdrawBinding
+import org.keepgoeat.presentation.type.WithdrawReason
+import org.keepgoeat.util.ItemDiffCallback
+
+class WithdrawReasonAdapter(
+ private val selectReasons: (WithdrawReason) -> Unit,
+) :
+ ListAdapter(
+ ItemDiffCallback(
+ onContentsTheSame = { old, new -> old == new },
+ onItemsTheSame = { old, new -> old.reason == new.reason }
+ )
+ ) {
+ private lateinit var inflater: LayoutInflater
+
+ init {
+ submitList(WithdrawReason.values().toMutableList())
+ }
+
+ class WithdrawViewHolder(
+ private val binding: ItemWithdrawBinding,
+ ) : RecyclerView.ViewHolder(binding.root) {
+ var isClicked: Boolean = false
+ fun bind(
+ reason: WithdrawReason,
+ selectReasons: (WithdrawReason) -> Unit,
+ ) {
+ binding.reason = reason.reason
+ binding.layoutWithdrawReason.setOnClickListener {
+ isClicked = !isClicked
+ binding.isClicked = isClicked
+ selectReasons(reason)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WithdrawViewHolder {
+ if (!::inflater.isInitialized)
+ inflater = LayoutInflater.from(parent.context)
+ return WithdrawViewHolder(ItemWithdrawBinding.inflate(inflater, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: WithdrawViewHolder, position: Int) {
+ holder.bind(currentList[position], selectReasons)
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingActivity.kt b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingActivity.kt
new file mode 100644
index 00000000..06a844af
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingActivity.kt
@@ -0,0 +1,86 @@
+package org.keepgoeat.presentation.onboarding
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.viewpager2.widget.ViewPager2
+import com.google.android.material.tabs.TabLayoutMediator
+import dagger.hilt.android.AndroidEntryPoint
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityOnboardingBinding
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.base.screen.BindingActivity
+
+@AndroidEntryPoint
+class OnboardingActivity :
+ BindingActivity(R.layout.activity_onboarding) {
+ private val viewModel: OnboardingViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ initLayout()
+ addListeners()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ stopRecodingScreenTime(viewModel.onboardingType.value.ordinal)
+ }
+
+ private fun initLayout() {
+ with(binding) {
+ vpViewPager.adapter = OnboardingAdapter(this@OnboardingActivity)
+ vpViewPager.registerOnPageChangeCallback(getPageChangeCallback())
+ TabLayoutMediator(indicator, vpViewPager) { _, _ -> }.attach()
+ }
+ }
+
+ private fun getPageChangeCallback() =
+ object : ViewPager2.OnPageChangeCallback() {
+ var prevPos = viewModel.onboardingType.value.ordinal
+
+ override fun onPageSelected(position: Int) {
+ super.onPageSelected(position)
+
+ viewModel.setOnboardingType(position)
+ recodeScreenTime(prevPos, position)
+ prevPos = position
+ }
+ }
+
+ private fun addListeners() {
+ binding.btnNext.setOnClickListener {
+ if (binding.vpViewPager.currentItem == viewModel.onboardingLastPos) {
+ viewModel.setClickedOnboardingButton()
+ moveToHome()
+ }
+ binding.vpViewPager.currentItem++
+ }
+ binding.tvSkip.setOnClickListener {
+ viewModel.setClickedOnboardingButton()
+ moveToHome()
+ }
+ }
+
+ private fun moveToHome() {
+ startActivity(Intent(this, HomeActivity::class.java))
+ finish()
+ }
+
+ /** ์ด์ ํฌ์ง์
์จ๋ณด๋ฉ ๋ทฐ์ ์คํฌ๋ฆฐํ์ ๊ธฐ๋ก์ ์ค๋จ, ํ์ฌ ํฌ์ง์
์จ๋ณด๋ฉ ๋ทฐ์ ์คํฌ๋ฆฐํ์์์ ๊ธฐ๋กํ๋ ํจ์ (๋จ, ์ด๊ธฐ ํฌ์ง์
์ด 0์ธ ๊ฒฝ์ฐ, if๋ฌธ์ ์คํํ์ง ์์.) */
+ private fun recodeScreenTime(prevPos: Int, curPos: Int) {
+ if (prevPos != curPos) stopRecodingScreenTime(prevPos)
+ viewModel.startRecodingScreenTime()
+ }
+
+ private fun stopRecodingScreenTime(pos: Int) {
+ viewModel.stopRecodingScreenTime("$SCREEN_NAME ${pos + 1}")
+ }
+
+ companion object {
+ private const val SCREEN_NAME = "onboarding"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingAdapter.kt b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingAdapter.kt
new file mode 100644
index 00000000..e5730695
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingAdapter.kt
@@ -0,0 +1,34 @@
+package org.keepgoeat.presentation.onboarding
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.databinding.ItemOnboardingBinding
+import org.keepgoeat.presentation.type.OnBoardingViewType
+
+class OnboardingAdapter(context: Context) :
+ RecyclerView.Adapter() {
+ private val inflater by lazy { LayoutInflater.from(context) }
+ private val onBoardingList = OnBoardingViewType.values()
+
+ init {
+ notifyDataSetChanged()
+ }
+
+ class OnBoardingViewHolder(private val binding: ItemOnboardingBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+ fun bind(onboarding: OnBoardingViewType) {
+ binding.item = onboarding
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OnBoardingViewHolder =
+ OnBoardingViewHolder(ItemOnboardingBinding.inflate(inflater, parent, false))
+
+ override fun onBindViewHolder(holder: OnBoardingViewHolder, position: Int) {
+ holder.bind(onBoardingList[position])
+ }
+
+ override fun getItemCount(): Int = onBoardingList.size
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingViewModel.kt
new file mode 100644
index 00000000..d89f5cb5
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/onboarding/OnboardingViewModel.kt
@@ -0,0 +1,29 @@
+package org.keepgoeat.presentation.onboarding
+
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.presentation.type.OnBoardingViewType
+import javax.inject.Inject
+
+@HiltViewModel
+class OnboardingViewModel @Inject constructor(private val localStorage: KGEDataSource) :
+ MixpanelViewModel() {
+ private val _onboardingType = MutableStateFlow(OnBoardingViewType.FIRST)
+ val onboardingType = _onboardingType.asStateFlow()
+ val onboardingLastPos = OnBoardingViewType.values().size - 1
+
+ fun setOnboardingType(position: Int) {
+ _onboardingType.value = when (position) {
+ OnBoardingViewType.FIRST.ordinal -> OnBoardingViewType.FIRST
+ OnBoardingViewType.SECOND.ordinal -> OnBoardingViewType.SECOND
+ else -> OnBoardingViewType.THIRD
+ }
+ }
+
+ fun setClickedOnboardingButton() {
+ localStorage.isClickedOnboardingButton = true
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingActivity.kt b/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingActivity.kt
new file mode 100644
index 00000000..efb510c0
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingActivity.kt
@@ -0,0 +1,114 @@
+package org.keepgoeat.presentation.setting
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ActivityGoalSettingBinding
+import org.keepgoeat.presentation.detail.GoalDetailActivity
+import org.keepgoeat.presentation.detail.GoalDetailActivity.Companion.ARG_GOAL_ID
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.model.GoalContent
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.presentation.base.screen.BindingActivity
+import org.keepgoeat.util.extension.*
+import org.keepgoeat.util.safeValueOf
+
+@AndroidEntryPoint
+class GoalSettingActivity :
+ BindingActivity(R.layout.activity_goal_setting) {
+ private val viewModel: GoalSettingViewModel by viewModels()
+ private var isEditMode: Boolean = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ intent.let {
+ it.getStringExtra(ARG_EATING_TYPE)?.let { strExtra ->
+ val eatingType = safeValueOf(strExtra) ?: return@let
+ viewModel.setEatingType(eatingType)
+ }
+
+ it.getParcelable(ARG_GOAL_CONTENT, GoalContent::class.java)?.let { goal ->
+ isEditMode = true
+ viewModel.setGoalContent(goal)
+ }
+ }
+
+ addListeners()
+ collectData()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.startRecodingScreenTime()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ viewModel.stopRecodingScreenTime(viewModel.eatingType.value?.name?.lowercase() ?: "")
+ }
+
+ private fun collectData() {
+ viewModel.uploadState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> {
+ if (isEditMode) {
+ showToast(getString(R.string.goal_setting_edit_success_toast_message))
+ moveToDetail()
+ } else {
+ showToast(getString(R.string.goal_setting_add_success_toast_message))
+ moveToHome()
+ }
+ }
+ is UiState.Error -> {}
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun addListeners() {
+ binding.root.setOnClickListener {
+ showKeyboard(it, false)
+ binding.etGoal.clearFocus()
+ binding.etGoalCriterion.clearFocus()
+ }
+ binding.viewToolbar.ivBack.setOnClickListener {
+ finish()
+ }
+ binding.btnComplete.setOnSingleClickListener {
+ showKeyboard(it, false)
+ viewModel.uploadGoal()
+ }
+ }
+
+ private fun moveToHome() {
+ val intent = Intent(this, HomeActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivity(intent)
+ }
+
+ private fun moveToDetail() {
+ val intent = Intent(this, GoalDetailActivity::class.java).apply {
+ putExtra(ARG_GOAL_ID, viewModel.goalId)
+ putExtra(ARG_IS_UPDATED, true)
+ putExtra(ARG_EATING_TYPE, viewModel.eatingType.value?.name)
+ }
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ startActivity(intent)
+ }
+
+ companion object {
+ const val ARG_EATING_TYPE = "eatingType"
+ const val ARG_GOAL_CONTENT = "goalContent"
+ const val ARG_IS_UPDATED = "isUpdated"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingViewModel.kt
new file mode 100644
index 00000000..3cf36f83
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/setting/GoalSettingViewModel.kt
@@ -0,0 +1,82 @@
+package org.keepgoeat.presentation.setting
+
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import org.keepgoeat.domain.repository.GoalRepository
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.presentation.model.GoalContent
+import org.keepgoeat.presentation.type.EatingType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.mixpanel.GoalEvent
+import org.keepgoeat.util.safeLet
+import timber.log.Timber
+import javax.inject.Inject
+
+@HiltViewModel
+class GoalSettingViewModel @Inject constructor(
+ private val goalRepository: GoalRepository,
+) : MixpanelViewModel() {
+ val goalFood = MutableStateFlow(null)
+ val goalCriterion = MutableStateFlow("")
+ private val _eatingType = MutableStateFlow(null)
+ val eatingType get() = _eatingType.asStateFlow()
+ var goalId: Int? = null
+
+ private val _uploadState = MutableStateFlow>(UiState.Loading)
+ val uploadState: StateFlow> get() = _uploadState
+
+ fun uploadGoal() {
+ if (goalId == null) addGoal()
+ else editGoal()
+ }
+
+ private fun addGoal() {
+ val title = goalFood.value?.trim() ?: return
+ val criterion = goalCriterion.value.trim()
+
+ viewModelScope.launch {
+ goalRepository.uploadGoalContent(
+ title,
+ criterion,
+ eatingType.value == EatingType.MORE
+ ).onSuccess {
+ _uploadState.value = UiState.Success(it)
+ with(mixpanelProvider) {
+ createGoal()
+ sendEvent(GoalEvent.createGoal(title, criterion))
+ }
+ }.onFailure {
+ _uploadState.value = UiState.Error(it.message)
+ Timber.e(it.message)
+ }
+ }
+ }
+
+ private fun editGoal() {
+ viewModelScope.launch {
+ safeLet(goalId, goalFood.value, goalCriterion.value) { id, food, criterion ->
+ goalRepository.editGoalContent(id, food, criterion)
+ .onSuccess {
+ _uploadState.value = UiState.Success(it)
+ }.onFailure {
+ _uploadState.value = UiState.Error(it.message)
+ Timber.e(it.message)
+ }
+ }
+ }
+ }
+
+ fun setEatingType(eatingType: EatingType) {
+ _eatingType.value = eatingType
+ }
+
+ fun setGoalContent(goal: GoalContent) {
+ goalId = goal.id
+ goalFood.value = goal.food
+ goalCriterion.value = goal.criterion
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/sign/SignActivity.kt b/app/src/main/java/org/keepgoeat/presentation/sign/SignActivity.kt
new file mode 100644
index 00000000..8a9385da
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/sign/SignActivity.kt
@@ -0,0 +1,75 @@
+package org.keepgoeat.presentation.sign
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.keepgoeat.R
+import org.keepgoeat.data.service.KakaoAuthService
+import org.keepgoeat.data.service.NaverAuthService
+import org.keepgoeat.databinding.ActivitySignBinding
+import org.keepgoeat.presentation.base.screen.MixpanelActivity
+import org.keepgoeat.presentation.home.HomeActivity
+import org.keepgoeat.presentation.onboarding.OnboardingActivity
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.extension.showToast
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class SignActivity : MixpanelActivity(R.layout.activity_sign, SCREEN_NAME) {
+ @Inject
+ lateinit var kakaoSignService: KakaoAuthService
+
+ @Inject
+ lateinit var naverSignService: NaverAuthService
+ override val viewModel: SignViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ addListeners()
+ collectData()
+ }
+
+ private fun addListeners() {
+ binding.layoutKakaoSignIn.setOnClickListener {
+ kakaoSignService.loginKakao(viewModel::login, viewModel::saveAccount)
+ }
+ binding.layoutNaverSignIn.setOnClickListener {
+ naverSignService.loginNaver(viewModel::login, viewModel::saveAccount)
+ }
+ }
+
+ private fun collectData() {
+ viewModel.loginUiState.flowWithLifecycle(lifecycle).onEach {
+ when (it) {
+ is UiState.Success -> {
+ showToast(getString(R.string.signin_success_toast_message))
+ moveToNext(it.data)
+ }
+ is UiState.Error -> {
+ showToast(getString(R.string.signin_failure_toast_message))
+ }
+ else -> {}
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ /** ๊ฐ์
์๊ฐ ์จ๋ณด๋ฉ ๋ชจ๋ ํ์ธ(์๋ต ํฌํจ)ํ์ง ์์ ๊ฒฝ์ฐ ์จ๋ณด๋ฉ ํ๋ฉด์ผ๋ก ๊ทธ ์ธ์ ๊ฒฝ์ฐ(๊ฐ์
์๊ฐ ์จ๋ณด๋ฉ์์ ์ค๊ฐ ์ดํ + ๋ก๊ทธ์ธํ ์ฌ์ฉ์)๋ ํํ๋ฉด์ผ๋ก ์ด๋ */
+ /** @param onboardingFlag : first๋ ๊ฐ์
์ ์ฌ๋ถ(true: ๊ฐ์
ํ ์ฌ์ฉ์, false: ๋ก๊ทธ์ธํ ์ฌ์ฉ์), second๋ ์จ๋ณด๋ฉ ์๋ฃ ๋ฒํผ์ ํด๋ฆญํ๋์ง ์ฌ๋ถ */
+ private fun moveToNext(onboardingFlag: Pair) {
+ val nextScreen =
+ if (onboardingFlag.first && !onboardingFlag.second) OnboardingActivity::class.java
+ else HomeActivity::class.java
+ startActivity(Intent(this, nextScreen))
+ finish()
+ }
+
+ companion object {
+ private const val SCREEN_NAME = "signup"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/sign/SignViewModel.kt b/app/src/main/java/org/keepgoeat/presentation/sign/SignViewModel.kt
new file mode 100644
index 00000000..c677dce0
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/sign/SignViewModel.kt
@@ -0,0 +1,67 @@
+package org.keepgoeat.presentation.sign
+
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.data.model.request.RequestAuth
+import org.keepgoeat.domain.model.AccountInfo
+import org.keepgoeat.domain.repository.AuthRepository
+import org.keepgoeat.domain.type.SignType
+import org.keepgoeat.presentation.base.viewmodel.MixpanelViewModel
+import org.keepgoeat.presentation.type.LoginPlatformType
+import org.keepgoeat.util.UiState
+import org.keepgoeat.util.mixpanel.SignEvent
+import javax.inject.Inject
+
+@HiltViewModel
+class SignViewModel @Inject constructor(
+ private val authRepository: AuthRepository,
+ private val localStorage: KGEDataSource,
+) : MixpanelViewModel() {
+ private val _loginUiState = MutableStateFlow>>(UiState.Loading)
+ val loginUiState get() = _loginUiState.asStateFlow()
+
+ fun login(loginPlatForm: LoginPlatformType, accessToken: String) {
+ localStorage.loginPlatform = loginPlatForm
+ viewModelScope.launch {
+ authRepository.login(
+ RequestAuth(accessToken, loginPlatForm.name)
+ ).onSuccess {
+ val isSignUp = it?.signType == SignType.SIGN_UP
+ _loginUiState.value = UiState.Success(
+ Pair(isSignUp, localStorage.isClickedOnboardingButton)
+ )
+ initMixpanelGoalNumber(isSignUp)
+ sendSignEventLog(it?.signType, loginPlatForm.label)
+ }.onFailure {
+ _loginUiState.value = UiState.Error(it.message)
+ }
+ }
+ }
+
+ fun saveAccount(accountInfo: AccountInfo) {
+ localStorage.userName = accountInfo.name
+ localStorage.userEmail = accountInfo.email
+ mixpanelProvider.setUserProfile()
+ }
+
+ /** ํ์๊ฐ์
์์๋ง ์ ์ ํ๋กํผํฐ > ๋ชฉํ์๋ฅผ ์ด๊ธฐํํ๋ ํจ์ */
+ private fun initMixpanelGoalNumber(isSignUp: Boolean) {
+ if (isSignUp) mixpanelProvider.initUserGoalNumber()
+ }
+
+ private fun sendSignEventLog(signType: SignType?, platform: String) {
+ when (signType) {
+ SignType.SIGN_UP -> {
+ mixpanelProvider.sendEvent(SignEvent.completeSignUp(platform))
+ }
+ SignType.SIGN_IN -> {
+ mixpanelProvider.sendEvent(SignEvent.completeLogin())
+ }
+ else -> {}
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/EatingType.kt b/app/src/main/java/org/keepgoeat/presentation/type/EatingType.kt
new file mode 100644
index 00000000..d1231d2b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/EatingType.kt
@@ -0,0 +1,61 @@
+package org.keepgoeat.presentation.type
+
+import android.graphics.Color
+import androidx.annotation.ColorInt
+import androidx.annotation.ColorRes
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import org.keepgoeat.R
+
+enum class EatingType(
+ @StringRes val strRes: Int,
+ @StringRes val titleStrRes: Int,
+ @StringRes val achievementCountTitle: Int,
+ @DrawableRes val snailStickerRes: Int,
+ @DrawableRes val defaultStickerRes: Int,
+ @DrawableRes val tagIconRes: Int,
+ @DrawableRes val snailCheerInKeepRes: Int,
+ @ColorRes val tagTextColor: Int,
+ @ColorRes val tagBackgroundColor: Int,
+ @ColorRes val thisMonthTextColor: Int,
+ @ColorRes val buttonBackgroundColor: Int,
+ @ColorRes val buttonTextColor: Int,
+ @ColorRes val buttonRippleColor: Int,
+ @ColorRes val achievedGoalDayTextColor: Int,
+ @ColorInt val cardBackgroundColor: Int,
+) {
+ LESS(
+ R.string.eating_type_less,
+ R.string.title_less,
+ R.string.goal_detail_hold,
+ R.drawable.ic_snail_green_sticker,
+ R.drawable.ic_default_green_sticker,
+ R.drawable.ic_eating_less_tag_minus,
+ R.drawable.ic_snail_green_cheer_left,
+ R.color.green_600,
+ R.color.green_200,
+ R.color.green_700,
+ R.color.green_500,
+ R.color.white,
+ R.color.green_700,
+ R.color.green_600,
+ Color.parseColor("#EAFBF4"),
+ ),
+ MORE(
+ R.string.eating_type_more,
+ R.string.title_more,
+ R.string.goal_detail_eat,
+ R.drawable.ic_snail_orange_sticker,
+ R.drawable.ic_default_orange_sticker,
+ R.drawable.ic_eating_more_tag_plus,
+ R.drawable.ic_snail_orange_cheer_left,
+ R.color.orange_600,
+ R.color.orange_100,
+ R.color.orange_600,
+ R.color.orange_600,
+ R.color.gray_50,
+ R.color.orange_700,
+ R.color.orange_500,
+ Color.parseColor("#FFF0EB"),
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/HomeBackgroundType.kt b/app/src/main/java/org/keepgoeat/presentation/type/HomeBackgroundType.kt
new file mode 100644
index 00000000..3e00a75d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/HomeBackgroundType.kt
@@ -0,0 +1,12 @@
+package org.keepgoeat.presentation.type
+
+import androidx.annotation.DrawableRes
+import org.keepgoeat.R
+
+enum class HomeBackgroundType(
+ @DrawableRes val sky: Int
+) {
+ MORNING(R.drawable.img_home_background_morning),
+ EVENING(R.drawable.img_home_background_evening),
+ NIGHT(R.drawable.img_home_background_night)
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/HomeBtnType.kt b/app/src/main/java/org/keepgoeat/presentation/type/HomeBtnType.kt
new file mode 100644
index 00000000..c51edb08
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/HomeBtnType.kt
@@ -0,0 +1,38 @@
+package org.keepgoeat.presentation.type
+
+import androidx.annotation.ColorRes
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import org.keepgoeat.R
+
+enum class HomeBtnType(
+ @ColorRes val btnColorInt: Int,
+ @DrawableRes val btnDrawableRes: Int,
+ @StringRes val btnStringRes: Int,
+ @ColorRes val btnTextColorInt: Int
+) {
+ MINUS_ACHIEVED(
+ R.color.green_100,
+ R.drawable.ic_check_green,
+ R.string.home_goal_less_achieved,
+ R.color.green_600
+ ),
+ MINUS_NOT_ACHIEVED(
+ R.color.green_500,
+ R.drawable.ic_check,
+ R.string.home_goal_less_btn,
+ R.color.gray_50
+ ),
+ PLUS_ACHIEVED(
+ R.color.orange_50,
+ R.drawable.ic_check_orange,
+ R.string.home_goal_more_achieved,
+ R.color.orange_600
+ ),
+ PLUS_NOT_ACHIEVED(
+ R.color.orange_600,
+ R.drawable.ic_check,
+ R.string.home_goal_more_btn,
+ R.color.gray_50
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/HomeGoalViewType.kt b/app/src/main/java/org/keepgoeat/presentation/type/HomeGoalViewType.kt
new file mode 100644
index 00000000..d5b0dd2d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/HomeGoalViewType.kt
@@ -0,0 +1,6 @@
+package org.keepgoeat.presentation.type
+
+enum class HomeGoalViewType {
+ MY_GOAL_TYPE,
+ ADD_GOAL_TYPE
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/LoginPlatformType.kt b/app/src/main/java/org/keepgoeat/presentation/type/LoginPlatformType.kt
new file mode 100644
index 00000000..8912dd8b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/LoginPlatformType.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.presentation.type
+
+enum class LoginPlatformType(val label: String) {
+ NAVER("Naver"), KAKAO("Kakao"), NONE("None")
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/OnBoardingViewType.kt b/app/src/main/java/org/keepgoeat/presentation/type/OnBoardingViewType.kt
new file mode 100644
index 00000000..9b8f3680
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/OnBoardingViewType.kt
@@ -0,0 +1,31 @@
+package org.keepgoeat.presentation.type
+
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import org.keepgoeat.R
+
+enum class OnBoardingViewType(
+ @StringRes val titleStrRes: Int,
+ @StringRes val desStrRes: Int,
+ @StringRes val btnTextRes: Int,
+ @DrawableRes val imageRes: Int,
+) {
+ FIRST(
+ R.string.onboarding1_title,
+ R.string.onboarding1_des,
+ R.string.onboarding1_button,
+ R.drawable.img_onboarding_1
+ ),
+ SECOND(
+ R.string.onboarding2_title,
+ R.string.onboarding2_des,
+ R.string.onboarding2_button,
+ R.drawable.img_onboarding_2
+ ),
+ THIRD(
+ R.string.onboarding3_title,
+ R.string.onboarding3_des,
+ R.string.onboarding3_button,
+ R.drawable.img_onboarding_3
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/ProcessState.kt b/app/src/main/java/org/keepgoeat/presentation/type/ProcessState.kt
new file mode 100644
index 00000000..bd4fad56
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/ProcessState.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.presentation.type
+
+enum class ProcessState {
+ IDLE, IN_PROGRESS, DONE
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/RecyclerLayoutType.kt b/app/src/main/java/org/keepgoeat/presentation/type/RecyclerLayoutType.kt
new file mode 100644
index 00000000..cc6889db
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/RecyclerLayoutType.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.presentation.type
+
+enum class RecyclerLayoutType {
+ HORIZONTAL, VERTICAL, GRID
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/SortType.kt b/app/src/main/java/org/keepgoeat/presentation/type/SortType.kt
new file mode 100644
index 00000000..11da00bb
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/SortType.kt
@@ -0,0 +1,5 @@
+package org.keepgoeat.presentation.type
+
+enum class SortType {
+ MORE, LESS, ALL
+}
diff --git a/app/src/main/java/org/keepgoeat/presentation/type/WithdrawReason.kt b/app/src/main/java/org/keepgoeat/presentation/type/WithdrawReason.kt
new file mode 100644
index 00000000..b1ff1321
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/presentation/type/WithdrawReason.kt
@@ -0,0 +1,13 @@
+package org.keepgoeat.presentation.type
+
+import androidx.annotation.StringRes
+import org.keepgoeat.R
+
+enum class WithdrawReason(
+ @StringRes val reason: Int,
+) {
+ QUIT_ISSUE(R.string.withdraw_reason1),
+ FREQUENCY_ISSUE(R.string.withdraw_reason2),
+ ERROR_ISSUE(R.string.withdraw_reason3),
+ CONTENT_ISSUE(R.string.withdraw_reason4),
+}
diff --git a/app/src/main/java/org/keepgoeat/util/BindingAdatper.kt b/app/src/main/java/org/keepgoeat/util/BindingAdatper.kt
index 20af0143..fa8f23bf 100644
--- a/app/src/main/java/org/keepgoeat/util/BindingAdatper.kt
+++ b/app/src/main/java/org/keepgoeat/util/BindingAdatper.kt
@@ -1,10 +1,16 @@
package org.keepgoeat.util
+import android.text.InputFilter
import android.view.View
+import android.widget.EditText
import android.widget.ImageView
+import android.widget.TextView
import androidx.core.view.isVisible
+import androidx.core.widget.addTextChangedListener
import androidx.databinding.BindingAdapter
import coil.load
+import org.keepgoeat.presentation.type.HomeBackgroundType
+import org.keepgoeat.util.extension.getStringLength
@BindingAdapter("image")
fun ImageView.setImage(imageUrl: String) {
@@ -16,3 +22,52 @@ fun View.setVisibility(isVisible: Boolean?) {
if (isVisible == null) return
this.isVisible = isVisible
}
+
+/*
+@BindingAdapter(value = ["startDate", "endDate"], requireAll = false)
+fun TextView.setDuration(startDate: LocalDate?, endDate: LocalDate?) {
+ safeLet(startDate, endDate) { s, e ->
+ text = String.format(
+ context.getString(R.string.my_goal_duration_format),
+ s.year,
+ s.monthValue.padZero(2),
+ s.dayOfMonth.padZero(2),
+ e.year,
+ e.monthValue.padZero(2),
+ e.dayOfMonth.padZero(2)
+ )
+ }
+}
+*/
+
+@BindingAdapter(value = ["startDate", "endDate"], requireAll = false)
+fun TextView.setDurationText(startDate: String?, endDate: String?) {
+ safeLet(startDate, endDate) { s, e ->
+ text = "$s ~ $e"
+ }
+}
+
+@BindingAdapter("homeBackground")
+fun ImageView.setBackground(hour: Int) {
+ val imgRes = when (hour) {
+ in 7..16 -> HomeBackgroundType.MORNING.sky
+ in 18..24, in 0..5 -> HomeBackgroundType.NIGHT.sky
+ in 5..7, in 16..18 -> HomeBackgroundType.EVENING.sky
+ else -> {
+ HomeBackgroundType.MORNING.sky
+ }
+ }
+ setBackgroundResource(imgRes)
+}
+
+/** ์์คํ
์ด ์ธ์ํ๋ ๊ธ์ ์๋ฅผ ์ฌ์ฉ์๊ฐ ์ธ์ํ๋ ๊ธ์ ์๋ก ๋ณํํด์ ๊ธ์ ์ ๋ฒ์์ ๋ฐ๋ผ maxLength ๋ฅผ ์ค์ */
+@BindingAdapter("maxLen")
+fun EditText.cutTextToMaxLength(maxLength: Int) {
+ val filterArray = arrayOfNulls(1)
+ addTextChangedListener {
+ val str = text.toString()
+ val lengthFilter =
+ if (str.getStringLength() == maxLength) str.length else Int.MAX_VALUE
+ filters = filterArray.apply { this[0] = InputFilter.LengthFilter(lengthFilter) }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/Event.kt b/app/src/main/java/org/keepgoeat/util/Event.kt
deleted file mode 100644
index 4a55ef3e..00000000
--- a/app/src/main/java/org/keepgoeat/util/Event.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.keepgoeat.util
-
-open class Event(private val content: T) {
- var hasBeenHandled = false
- private set
-
- fun getContentIfNotHandled(): T? {
- return if (hasBeenHandled) {
- null
- } else {
- hasBeenHandled = true
- content
- }
- }
-
- fun peekContent(): T = content
-}
diff --git a/app/src/main/java/org/keepgoeat/util/EventObserver.kt b/app/src/main/java/org/keepgoeat/util/EventObserver.kt
deleted file mode 100644
index 92c4d279..00000000
--- a/app/src/main/java/org/keepgoeat/util/EventObserver.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keepgoeat.util
-
-import androidx.lifecycle.Observer
-
-class EventObserver(private val onEventUnhandledContent: (T) -> Unit) : Observer> {
- override fun onChanged(event: Event?) {
- event?.getContentIfNotHandled()?.let { value ->
- onEventUnhandledContent(value)
- }
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/util/ItemDecorationUtil.kt b/app/src/main/java/org/keepgoeat/util/ItemDecorationUtil.kt
new file mode 100644
index 00000000..0fd59c06
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/ItemDecorationUtil.kt
@@ -0,0 +1,40 @@
+package org.keepgoeat.util
+
+import android.graphics.Rect
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import org.keepgoeat.presentation.type.RecyclerLayoutType
+import org.keepgoeat.util.extension.dp
+
+/** @param space : ์ฌ๋ฐฑ ์ฌ์ด์ฆ
+ * @param gridMatrix : ๊ทธ๋ฆฌ๋ ๋ ์ด์์ ๋ฉ๋์ ์ ์ฉ ์ row, colume ์๋ฅผ ๋ํ๋ด๋ Pair
+ * @param layoutType : ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ ๋ ์ด์์ ๋ฐฐ์น ๋ฐฉ์ */
+class ItemDecorationUtil(
+ private val space: Int,
+ private val gridMatrix: Pair? = null,
+ private val layoutType: RecyclerLayoutType,
+) : RecyclerView.ItemDecoration() {
+ private val spaceDp = space.dp
+ private val zeroDp = 0.dp
+
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ super.getItemOffsets(outRect, view, parent, state)
+ val pos = parent.getChildAdapterPosition(view)
+
+ when (layoutType) {
+ RecyclerLayoutType.GRID -> {
+ if (gridMatrix == null) return
+
+ with(gridMatrix) {
+ outRect.bottom = if (pos / second + 1 < first) spaceDp else zeroDp
+ outRect.right = if (pos % second + 1 < second) spaceDp else zeroDp
+ }
+ }
+ RecyclerLayoutType.VERTICAL -> {
+ val isLastItem = pos == parent.adapter?.itemCount?.minus(1)
+ outRect.bottom = if (!isLastItem) spaceDp else zeroDp
+ }
+ else -> {}
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/KGESnackbar.kt b/app/src/main/java/org/keepgoeat/util/KGESnackbar.kt
new file mode 100644
index 00000000..601385e7
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/KGESnackbar.kt
@@ -0,0 +1,60 @@
+package org.keepgoeat.util
+
+import android.annotation.SuppressLint
+import android.graphics.Color
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.LinearLayout
+import androidx.databinding.DataBindingUtil
+import com.google.android.material.snackbar.BaseTransientBottomBar.ANIMATION_MODE_FADE
+import com.google.android.material.snackbar.Snackbar
+import org.keepgoeat.R
+import org.keepgoeat.databinding.ViewKgeSnackbarBinding
+
+class KGESnackbar(
+ private val view: View,
+ private val message: String,
+ private val duration: Int,
+ private val isTop: Boolean,
+) {
+ private val snackbar = Snackbar.make(view, "", duration)
+ private val snackbarLayout = snackbar.view as Snackbar.SnackbarLayout
+ private val snackbarBinding: ViewKgeSnackbarBinding =
+ DataBindingUtil.inflate(
+ LayoutInflater.from(view.context),
+ R.layout.view_kge_snackbar,
+ null,
+ false
+ ).apply {
+ tvMessage.text = message
+ }
+ private val layoutParams = LinearLayout.LayoutParams(snackbar.view.layoutParams)
+
+ init {
+ initializeView()
+ }
+
+ @SuppressLint("RestrictedApi")
+ private fun initializeView() {
+ with(snackbarLayout) {
+ removeAllViews()
+ if (isTop) {
+ this@KGESnackbar.layoutParams.gravity = Gravity.TOP
+ layoutParams = this@KGESnackbar.layoutParams
+ snackbar.animationMode = ANIMATION_MODE_FADE
+ }
+ setBackgroundColor(Color.TRANSPARENT)
+ setPadding(0, 0, 0, 0)
+ addView(snackbarBinding.root, 0)
+ }
+ }
+
+ fun show() {
+ snackbar.show()
+ }
+
+ fun dismiss() {
+ if (duration == Snackbar.LENGTH_INDEFINITE) snackbar.dismiss()
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/NetworkMonitor.kt b/app/src/main/java/org/keepgoeat/util/NetworkMonitor.kt
new file mode 100644
index 00000000..a721e5f1
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/NetworkMonitor.kt
@@ -0,0 +1,39 @@
+package org.keepgoeat.util
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.Network
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.callbackFlow
+import org.keepgoeat.util.extension.toStateFlow
+
+/* ref :
+https://developer.android.com/training/basics/network-ops/reading-network-state
+https://medium.com/@bazzairvine/observing-your-network-connection-with-flow-1cdedf31780c */
+
+class NetworkMonitor(private val context: Context, private val coroutineScope: CoroutineScope) {
+ private val connectivityManager: ConnectivityManager =
+ context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+
+ val isConnected: StateFlow = callbackFlow {
+ val callback = object : ConnectivityManager.NetworkCallback() {
+ override fun onAvailable(network: Network) {
+ super.onAvailable(network)
+ trySend(true)
+ }
+
+ override fun onLost(network: Network) {
+ super.onLost(network)
+ trySend(false)
+ }
+ }
+
+ connectivityManager.registerDefaultNetworkCallback(callback)
+
+ awaitClose {
+ connectivityManager.unregisterNetworkCallback(callback)
+ }
+ }.toStateFlow(coroutineScope, false)
+}
diff --git a/app/src/main/java/org/keepgoeat/util/UiState.kt b/app/src/main/java/org/keepgoeat/util/UiState.kt
new file mode 100644
index 00000000..23afc793
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/UiState.kt
@@ -0,0 +1,8 @@
+package org.keepgoeat.util
+
+sealed class UiState {
+ object Loading : UiState()
+ object Empty : UiState()
+ data class Success(val data: T) : UiState()
+ data class Error(val message: String?) : UiState()
+}
diff --git a/app/src/main/java/org/keepgoeat/util/binding/BindingActivity.kt b/app/src/main/java/org/keepgoeat/util/binding/BindingActivity.kt
deleted file mode 100644
index e22a0d83..00000000
--- a/app/src/main/java/org/keepgoeat/util/binding/BindingActivity.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.keepgoeat.util.binding
-
-import android.os.Bundle
-import androidx.annotation.LayoutRes
-import androidx.appcompat.app.AppCompatActivity
-import androidx.databinding.DataBindingUtil
-import androidx.databinding.ViewDataBinding
-
-abstract class BindingActivity(@LayoutRes private val layoutRes: Int) :
- AppCompatActivity() {
- lateinit var binding: B
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = DataBindingUtil.setContentView(this, layoutRes)
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/util/extension/ActivityExt.kt b/app/src/main/java/org/keepgoeat/util/extension/ActivityExt.kt
index bb386067..6cc418ec 100644
--- a/app/src/main/java/org/keepgoeat/util/extension/ActivityExt.kt
+++ b/app/src/main/java/org/keepgoeat/util/extension/ActivityExt.kt
@@ -1,3 +1,5 @@
+package org.keepgoeat.util.extension
+
import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
diff --git a/app/src/main/java/org/keepgoeat/util/extension/ContextExt.kt b/app/src/main/java/org/keepgoeat/util/extension/ContextExt.kt
index 57b9f33d..963065a9 100644
--- a/app/src/main/java/org/keepgoeat/util/extension/ContextExt.kt
+++ b/app/src/main/java/org/keepgoeat/util/extension/ContextExt.kt
@@ -11,9 +11,9 @@ fun Context.showToast(message: String, isShort: Boolean = true) {
Toast.makeText(this, message, duration).show()
}
-fun Context.showKeyboard(view: View, toShow: Boolean) {
+fun Context.showKeyboard(view: View, isShown: Boolean = true) {
(getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager).run {
- if (toShow) showSoftInput(view, 0)
+ if (isShown) showSoftInput(view, 0)
else hideSoftInputFromWindow(view.windowToken, 0)
}
}
diff --git a/app/src/main/java/org/keepgoeat/util/extension/FlowExt.kt b/app/src/main/java/org/keepgoeat/util/extension/FlowExt.kt
new file mode 100644
index 00000000..11b9a03b
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/extension/FlowExt.kt
@@ -0,0 +1,9 @@
+package org.keepgoeat.util.extension
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.stateIn
+
+fun Flow.toStateFlow(coroutineScope: CoroutineScope, initialValue: T) =
+ stateIn(coroutineScope, SharingStarted.Eagerly, initialValue)
diff --git a/app/src/main/java/org/keepgoeat/util/extension/IntExt.kt b/app/src/main/java/org/keepgoeat/util/extension/IntExt.kt
new file mode 100644
index 00000000..67289c7d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/extension/IntExt.kt
@@ -0,0 +1,9 @@
+package org.keepgoeat.util.extension
+
+import android.content.res.Resources
+import kotlin.math.roundToInt
+
+val Int.dp: Int
+ get() = (this * Resources.getSystem().displayMetrics.density).roundToInt()
+
+fun Int.padZero(length: Int) = toString().padStart(length, '0')
diff --git a/app/src/main/java/org/keepgoeat/util/extension/LivedataExt.kt b/app/src/main/java/org/keepgoeat/util/extension/LivedataExt.kt
deleted file mode 100644
index d5b19ce0..00000000
--- a/app/src/main/java/org/keepgoeat/util/extension/LivedataExt.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.keepgoeat.util.extension
-
-import androidx.lifecycle.MediatorLiveData
-import androidx.lifecycle.MutableLiveData
-
-fun MediatorLiveData.addSourceList(
- vararg liveDataArgument: MutableLiveData<*>,
- onChanged: () -> T,
-) {
- liveDataArgument.forEach {
- this.addSource(it) { value = onChanged() }
- }
-}
diff --git a/app/src/main/java/org/keepgoeat/util/extension/StringExt.kt b/app/src/main/java/org/keepgoeat/util/extension/StringExt.kt
new file mode 100644
index 00000000..66dad3a6
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/extension/StringExt.kt
@@ -0,0 +1,15 @@
+package org.keepgoeat.util.extension
+
+import java.text.BreakIterator
+
+/** ์ฌ์ฉ์๊ฐ ์ธ์ํ๋ ๋ฌธ์์ด์ ๊ธ์ ์๋ฅผ ๋ฐํํ๋ ํจ์ */
+fun String?.getStringLength(): Int {
+ if (this == null) return 0
+ val it: BreakIterator = BreakIterator.getCharacterInstance()
+ it.setText(this)
+ var count = 0
+ while (it.next() != BreakIterator.DONE) {
+ count++
+ }
+ return count
+}
diff --git a/app/src/main/java/org/keepgoeat/util/extension/ViewExt.kt b/app/src/main/java/org/keepgoeat/util/extension/ViewExt.kt
index 9c7c07ee..a4a6ede9 100644
--- a/app/src/main/java/org/keepgoeat/util/extension/ViewExt.kt
+++ b/app/src/main/java/org/keepgoeat/util/extension/ViewExt.kt
@@ -7,3 +7,17 @@ fun View.showSnackbar(message: String, isShort: Boolean = true) {
val duration = if (isShort) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
Snackbar.make(this, message, duration).show()
}
+
+inline fun View.setOnSingleClickListener(
+ delay: Long = 500L,
+ crossinline block: (View) -> Unit,
+) {
+ var previousClickedTime = 0L
+ setOnClickListener { view ->
+ val clickedTime = System.currentTimeMillis()
+ if (clickedTime - previousClickedTime >= delay) {
+ block(view)
+ previousClickedTime = clickedTime
+ }
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/mixpanel/GoalEvent.kt b/app/src/main/java/org/keepgoeat/util/mixpanel/GoalEvent.kt
new file mode 100644
index 00000000..d444443d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/mixpanel/GoalEvent.kt
@@ -0,0 +1,27 @@
+package org.keepgoeat.util.mixpanel
+
+import org.keepgoeat.presentation.model.MixPanelEvent
+
+object GoalEvent {
+ fun completeGoal(goalName: String, goalStandard: String) = MixPanelEvent(
+ "Complete Goal",
+ mapOf("Goal Name" to goalName, "Goal Standard" to goalStandard)
+ )
+
+ fun addGoal(eatingType: String) = MixPanelEvent(
+ "Add Goal",
+ mapOf("Goal Type" to eatingType)
+ )
+
+ fun createGoal(title: String, criterion: String) = MixPanelEvent(
+ "Create Goal",
+ mapOf("Goal Name" to title, "Goal Standard" to criterion)
+ )
+
+ fun deleteGoal() = MixPanelEvent("Delete Goal", null)
+
+ fun archiveGoal(goalName: String, goalStandard: String) = MixPanelEvent(
+ "Archive",
+ mapOf("Goal Name" to goalName, "Goal Standard" to goalStandard)
+ )
+}
diff --git a/app/src/main/java/org/keepgoeat/util/mixpanel/MixpanelProvider.kt b/app/src/main/java/org/keepgoeat/util/mixpanel/MixpanelProvider.kt
new file mode 100644
index 00000000..4449be8d
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/mixpanel/MixpanelProvider.kt
@@ -0,0 +1,90 @@
+package org.keepgoeat.util.mixpanel
+
+import android.content.Context
+import com.mixpanel.android.mpmetrics.MixpanelAPI
+import dagger.hilt.android.qualifiers.ApplicationContext
+import org.json.JSONObject
+import org.keepgoeat.BuildConfig
+import org.keepgoeat.data.datasource.local.KGEDataSource
+import org.keepgoeat.presentation.model.MixPanelEvent
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class MixpanelProvider @Inject constructor(
+ @ApplicationContext private val context: Context,
+ private val localStorage: KGEDataSource,
+) {
+ private val instance: MixpanelAPI =
+ MixpanelAPI.getInstance(context, BuildConfig.MIXPANEL_PROJECT_TOKEN, true)
+
+ fun setUserProfile() {
+ if (BuildConfig.DEBUG) return
+ instance.identify("${localStorage.loginPlatform.label} ${localStorage.userEmail}")
+
+ val props = JSONObject().apply {
+ put(PROPERTY_NICKNAME, localStorage.userName)
+ put(PROPERTY_EMAIL, localStorage.userEmail)
+ put(PROPERTY_PLATFORM, localStorage.loginPlatform.label)
+ }
+
+ instance.people.set(props)
+ }
+
+ fun initUserGoalNumber() {
+ instance.people.set(PROPERTY_GOAL_NUMBER, 0)
+ }
+
+ private fun getUserProperties() = JSONObject().apply {
+ put(PROPERTY_NICKNAME, localStorage.userName)
+ put(PROPERTY_EMAIL, localStorage.userEmail)
+ }
+
+ fun createGoal() {
+ if (BuildConfig.DEBUG) return
+ instance.people.increment(PROPERTY_GOAL_NUMBER, 1.0)
+ }
+
+ fun deleteGoal() {
+ if (BuildConfig.DEBUG) return
+ instance.people.increment(PROPERTY_GOAL_NUMBER, -1.0)
+ }
+
+ /** ๋ฏน์คํจ๋์ ์ด๋ฒคํธ๋ฅผ ์ ์กํ๋ ํจ์. ์ ์ ํ๋กํผํฐ๋ฅผ ํจ๊ป ์ ์กํด์ผํ๋ ๊ฒฝ์ฐ, isRequiredUserProps๋ฅผ false๋ก ์ค์ ํ์ */
+ fun sendEvent(event: MixPanelEvent, isRequiredUserProps: Boolean = true) {
+ if (BuildConfig.DEBUG) return
+ val props = if (isRequiredUserProps) getUserProperties() else JSONObject()
+
+ event.params?.let {
+ for ((key, value) in it)
+ props.put(key, value)
+ }
+
+ instance.track(event.name, props)
+ }
+
+ fun startRecodingScreenTime() {
+ if (BuildConfig.DEBUG) return
+ instance.timeEvent(EVENT_VIEW_PAGE)
+ }
+
+ fun stopRecodingScreenTime(screenName: String) {
+ if (BuildConfig.DEBUG) return
+ val props = JSONObject().apply {
+ put(PROPERTY_PAGE_NAME, screenName)
+ }
+ instance.track(EVENT_VIEW_PAGE, props)
+ }
+
+ companion object {
+ // User Property
+ private const val PROPERTY_NICKNAME = "\$name"
+ private const val PROPERTY_EMAIL = "\$email"
+ private const val PROPERTY_PLATFORM = "Platform"
+ private const val PROPERTY_GOAL_NUMBER = "Goal Number"
+
+ // Event Property
+ private const val EVENT_VIEW_PAGE = "View Page"
+ private const val PROPERTY_PAGE_NAME = "Page Name"
+ }
+}
diff --git a/app/src/main/java/org/keepgoeat/util/mixpanel/SignEvent.kt b/app/src/main/java/org/keepgoeat/util/mixpanel/SignEvent.kt
new file mode 100644
index 00000000..76c6c93c
--- /dev/null
+++ b/app/src/main/java/org/keepgoeat/util/mixpanel/SignEvent.kt
@@ -0,0 +1,11 @@
+package org.keepgoeat.util.mixpanel
+
+import org.keepgoeat.presentation.model.MixPanelEvent
+
+object SignEvent {
+ fun completeSignUp(platForm: String) = MixPanelEvent("Sign Up", mapOf("Platform" to platForm))
+
+ fun completeLogin() = MixPanelEvent("Login", null)
+
+ fun deleteAccount(reasons: Map?) = MixPanelEvent("Delete Account", reasons)
+}
diff --git a/app/src/main/res/color/selector_complete_button_text_color.xml b/app/src/main/res/color/selector_complete_button_text_color.xml
new file mode 100644
index 00000000..d5112a5c
--- /dev/null
+++ b/app/src/main/res/color/selector_complete_button_text_color.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/color/selector_less_complete_button_color.xml b/app/src/main/res/color/selector_less_complete_button_color.xml
new file mode 100644
index 00000000..d198bc8c
--- /dev/null
+++ b/app/src/main/res/color/selector_less_complete_button_color.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/color/selector_more_complete_button_color.xml b/app/src/main/res/color/selector_more_complete_button_color.xml
new file mode 100644
index 00000000..34b8b6fb
--- /dev/null
+++ b/app/src/main/res/color/selector_more_complete_button_color.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/img_home_background_evening.png b/app/src/main/res/drawable-hdpi/img_home_background_evening.png
new file mode 100644
index 00000000..9ac86176
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_home_background_evening.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_home_background_morning.png b/app/src/main/res/drawable-hdpi/img_home_background_morning.png
new file mode 100644
index 00000000..29b7678e
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_home_background_morning.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_home_background_night.png b/app/src/main/res/drawable-hdpi/img_home_background_night.png
new file mode 100644
index 00000000..66deca8f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_home_background_night.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_logo.png b/app/src/main/res/drawable-hdpi/img_logo.png
new file mode 100644
index 00000000..4c55a334
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_logo.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_onboarding_1.png b/app/src/main/res/drawable-hdpi/img_onboarding_1.png
new file mode 100644
index 00000000..4fe323cc
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_onboarding_1.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_onboarding_2.png b/app/src/main/res/drawable-hdpi/img_onboarding_2.png
new file mode 100644
index 00000000..351f05a0
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_onboarding_2.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_onboarding_3.png b/app/src/main/res/drawable-hdpi/img_onboarding_3.png
new file mode 100644
index 00000000..a4eda141
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_onboarding_3.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_service_intro_background.png b/app/src/main/res/drawable-hdpi/img_service_intro_background.png
new file mode 100644
index 00000000..45d8ee35
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_service_intro_background.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_service_intro_logo.png b/app/src/main/res/drawable-hdpi/img_service_intro_logo.png
new file mode 100644
index 00000000..ef2f848e
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_service_intro_logo.png differ
diff --git a/app/src/main/res/drawable-hdpi/img_snail_splash.png b/app/src/main/res/drawable-hdpi/img_snail_splash.png
new file mode 100644
index 00000000..26db87a4
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_snail_splash.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_home_background_evening.png b/app/src/main/res/drawable-mdpi/img_home_background_evening.png
new file mode 100644
index 00000000..6fce04cc
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_home_background_evening.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_home_background_morning.png b/app/src/main/res/drawable-mdpi/img_home_background_morning.png
new file mode 100644
index 00000000..21bc3d9a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_home_background_morning.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_home_background_night.png b/app/src/main/res/drawable-mdpi/img_home_background_night.png
new file mode 100644
index 00000000..38da8899
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_home_background_night.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_logo.png b/app/src/main/res/drawable-mdpi/img_logo.png
new file mode 100644
index 00000000..74bb7fdf
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_logo.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_onboarding_1.png b/app/src/main/res/drawable-mdpi/img_onboarding_1.png
new file mode 100644
index 00000000..5af72498
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_onboarding_1.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_onboarding_2.png b/app/src/main/res/drawable-mdpi/img_onboarding_2.png
new file mode 100644
index 00000000..662f752e
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_onboarding_2.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_onboarding_3.png b/app/src/main/res/drawable-mdpi/img_onboarding_3.png
new file mode 100644
index 00000000..f2971886
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_onboarding_3.png differ
diff --git a/app/src/main/res/drawable-mdpi/img_snail_splash.png b/app/src/main/res/drawable-mdpi/img_snail_splash.png
new file mode 100644
index 00000000..6cc232a1
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/img_snail_splash.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_home_background_evening.png b/app/src/main/res/drawable-xhdpi/img_home_background_evening.png
new file mode 100644
index 00000000..c7c78625
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_home_background_evening.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_home_background_morning.png b/app/src/main/res/drawable-xhdpi/img_home_background_morning.png
new file mode 100644
index 00000000..0430890d
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_home_background_morning.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_home_background_night.png b/app/src/main/res/drawable-xhdpi/img_home_background_night.png
new file mode 100644
index 00000000..6b5ec0cb
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_home_background_night.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_logo.png b/app/src/main/res/drawable-xhdpi/img_logo.png
new file mode 100644
index 00000000..c91e1f67
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_logo.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_onboarding_1.png b/app/src/main/res/drawable-xhdpi/img_onboarding_1.png
new file mode 100644
index 00000000..e122c1d4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_onboarding_1.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_onboarding_2.png b/app/src/main/res/drawable-xhdpi/img_onboarding_2.png
new file mode 100644
index 00000000..bdb7f791
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_onboarding_2.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_onboarding_3.png b/app/src/main/res/drawable-xhdpi/img_onboarding_3.png
new file mode 100644
index 00000000..86da9bf7
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_onboarding_3.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_service_intro_background.png b/app/src/main/res/drawable-xhdpi/img_service_intro_background.png
new file mode 100644
index 00000000..7b440fab
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_service_intro_background.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_service_intro_logo.png b/app/src/main/res/drawable-xhdpi/img_service_intro_logo.png
new file mode 100644
index 00000000..9f239d3a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_service_intro_logo.png differ
diff --git a/app/src/main/res/drawable-xhdpi/img_snail_splash.png b/app/src/main/res/drawable-xhdpi/img_snail_splash.png
new file mode 100644
index 00000000..3bc01a9e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_snail_splash.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_home_background_evening.png b/app/src/main/res/drawable-xxhdpi/img_home_background_evening.png
new file mode 100644
index 00000000..7a6a4abd
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_home_background_evening.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_home_background_morning.png b/app/src/main/res/drawable-xxhdpi/img_home_background_morning.png
new file mode 100644
index 00000000..5fd4adce
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_home_background_morning.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_home_background_night.png b/app/src/main/res/drawable-xxhdpi/img_home_background_night.png
new file mode 100644
index 00000000..8efb6dc6
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_home_background_night.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_logo.png b/app/src/main/res/drawable-xxhdpi/img_logo.png
new file mode 100644
index 00000000..6c0a6cdc
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_logo.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_onboarding_1.png b/app/src/main/res/drawable-xxhdpi/img_onboarding_1.png
new file mode 100644
index 00000000..9eb21e28
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_onboarding_1.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_onboarding_2.png b/app/src/main/res/drawable-xxhdpi/img_onboarding_2.png
new file mode 100644
index 00000000..407d5cfd
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_onboarding_2.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_onboarding_3.png b/app/src/main/res/drawable-xxhdpi/img_onboarding_3.png
new file mode 100644
index 00000000..078afcb7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_onboarding_3.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_service_intro_background.png b/app/src/main/res/drawable-xxhdpi/img_service_intro_background.png
new file mode 100644
index 00000000..277eca95
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_service_intro_background.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_service_intro_logo.png b/app/src/main/res/drawable-xxhdpi/img_service_intro_logo.png
new file mode 100644
index 00000000..07524a89
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_service_intro_logo.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/img_snail_splash.png b/app/src/main/res/drawable-xxhdpi/img_snail_splash.png
new file mode 100644
index 00000000..644c21fa
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_snail_splash.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_home_background_evening.png b/app/src/main/res/drawable-xxxhdpi/img_home_background_evening.png
new file mode 100644
index 00000000..1b1cd00b
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_home_background_evening.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_home_background_morning.png b/app/src/main/res/drawable-xxxhdpi/img_home_background_morning.png
new file mode 100644
index 00000000..d605098f
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_home_background_morning.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_home_background_night.png b/app/src/main/res/drawable-xxxhdpi/img_home_background_night.png
new file mode 100644
index 00000000..e80b5b82
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_home_background_night.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_logo.png b/app/src/main/res/drawable-xxxhdpi/img_logo.png
new file mode 100644
index 00000000..cf7aca7a
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_logo.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_onboarding_1.png b/app/src/main/res/drawable-xxxhdpi/img_onboarding_1.png
new file mode 100644
index 00000000..f4a88494
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_onboarding_1.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_onboarding_2.png b/app/src/main/res/drawable-xxxhdpi/img_onboarding_2.png
new file mode 100644
index 00000000..53786269
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_onboarding_2.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_onboarding_3.png b/app/src/main/res/drawable-xxxhdpi/img_onboarding_3.png
new file mode 100644
index 00000000..078737f9
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_onboarding_3.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_service_intro_background.png b/app/src/main/res/drawable-xxxhdpi/img_service_intro_background.png
new file mode 100644
index 00000000..f0f6b4ea
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_service_intro_background.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_service_intro_logo.png b/app/src/main/res/drawable-xxxhdpi/img_service_intro_logo.png
new file mode 100644
index 00000000..912ab790
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_service_intro_logo.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/img_snail_splash.png b/app/src/main/res/drawable-xxxhdpi/img_snail_splash.png
new file mode 100644
index 00000000..4861b674
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/img_snail_splash.png differ
diff --git a/app/src/main/res/drawable/background_cheer_msg.xml b/app/src/main/res/drawable/background_cheer_msg.xml
new file mode 100644
index 00000000..81af6f92
--- /dev/null
+++ b/app/src/main/res/drawable/background_cheer_msg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_goal_info.xml b/app/src/main/res/drawable/background_goal_info.xml
new file mode 100644
index 00000000..887b7b5d
--- /dev/null
+++ b/app/src/main/res/drawable/background_goal_info.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_goal_list.xml b/app/src/main/res/drawable/background_goal_list.xml
new file mode 100644
index 00000000..03c7e2ca
--- /dev/null
+++ b/app/src/main/res/drawable/background_goal_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_home_bottom.xml b/app/src/main/res/drawable/background_home_bottom.xml
new file mode 100644
index 00000000..604c4118
--- /dev/null
+++ b/app/src/main/res/drawable/background_home_bottom.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_keep_delete.xml b/app/src/main/res/drawable/background_keep_delete.xml
new file mode 100644
index 00000000..c9928fb3
--- /dev/null
+++ b/app/src/main/res/drawable/background_keep_delete.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_sign_box.xml b/app/src/main/res/drawable/background_sign_box.xml
new file mode 100644
index 00000000..26abb375
--- /dev/null
+++ b/app/src/main/res/drawable/background_sign_box.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml
new file mode 100644
index 00000000..37787112
--- /dev/null
+++ b/app/src/main/res/drawable/ic_back.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 00000000..65bc01c3
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_check_green.xml b/app/src/main/res/drawable/ic_check_green.xml
new file mode 100644
index 00000000..91cc52c5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check_green.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_check_orange.xml b/app/src/main/res/drawable/ic_check_orange.xml
new file mode 100644
index 00000000..7752f1b7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check_orange.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_checkbox_checked.xml b/app/src/main/res/drawable/ic_checkbox_checked.xml
new file mode 100644
index 00000000..664d25ae
--- /dev/null
+++ b/app/src/main/res/drawable/ic_checkbox_checked.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_checkbox_unchecked.xml b/app/src/main/res/drawable/ic_checkbox_unchecked.xml
new file mode 100644
index 00000000..c83d0044
--- /dev/null
+++ b/app/src/main/res/drawable/ic_checkbox_unchecked.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_default_green_sticker.xml b/app/src/main/res/drawable/ic_default_green_sticker.xml
new file mode 100644
index 00000000..46285e8f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_default_green_sticker.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_default_orange_sticker.xml b/app/src/main/res/drawable/ic_default_orange_sticker.xml
new file mode 100644
index 00000000..7070d6a2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_default_orange_sticker.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_detail.xml b/app/src/main/res/drawable/ic_detail.xml
new file mode 100644
index 00000000..ad33042d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_detail.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_detail_large.xml b/app/src/main/res/drawable/ic_detail_large.xml
new file mode 100644
index 00000000..ca0a0ca8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_detail_large.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_eating_less_tag_minus.xml b/app/src/main/res/drawable/ic_eating_less_tag_minus.xml
new file mode 100644
index 00000000..dbb323bb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_eating_less_tag_minus.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_eating_more_tag_plus.xml b/app/src/main/res/drawable/ic_eating_more_tag_plus.xml
new file mode 100644
index 00000000..bfea1d02
--- /dev/null
+++ b/app/src/main/res/drawable/ic_eating_more_tag_plus.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml
new file mode 100644
index 00000000..9d80cdab
--- /dev/null
+++ b/app/src/main/res/drawable/ic_edit.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_kakao.xml b/app/src/main/res/drawable/ic_kakao.xml
new file mode 100644
index 00000000..e05d34a4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_kakao.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_keep.xml b/app/src/main/res/drawable/ic_keep.xml
new file mode 100644
index 00000000..91206a81
--- /dev/null
+++ b/app/src/main/res/drawable/ic_keep.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_keepgoeat_background.xml b/app/src/main/res/drawable/ic_keepgoeat_background.xml
new file mode 100644
index 00000000..ca3826a4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_keepgoeat_background.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index 07d5da9c..ca3826a4 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,170 +1,74 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_more.xml b/app/src/main/res/drawable/ic_more.xml
new file mode 100644
index 00000000..94832da4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_more.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_my_page_white.xml b/app/src/main/res/drawable/ic_my_page_white.xml
new file mode 100644
index 00000000..7b23b01e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_my_page_white.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_naver.xml b/app/src/main/res/drawable/ic_naver.xml
new file mode 100644
index 00000000..defb2dfa
--- /dev/null
+++ b/app/src/main/res/drawable/ic_naver.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_plate_gray.xml b/app/src/main/res/drawable/ic_plate_gray.xml
new file mode 100644
index 00000000..d2458f0f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_plate_gray.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_plus.xml b/app/src/main/res/drawable/ic_plus.xml
new file mode 100644
index 00000000..dd916d7b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_plus.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_right.xml b/app/src/main/res/drawable/ic_right.xml
new file mode 100644
index 00000000..70f2c9be
--- /dev/null
+++ b/app/src/main/res/drawable/ic_right.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_green_cheer_left.xml b/app/src/main/res/drawable/ic_snail_green_cheer_left.xml
new file mode 100644
index 00000000..82aa0d02
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_green_cheer_left.xml
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_green_ribbon.xml b/app/src/main/res/drawable/ic_snail_green_ribbon.xml
new file mode 100644
index 00000000..db6e045a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_green_ribbon.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_green_sticker.xml b/app/src/main/res/drawable/ic_snail_green_sticker.xml
new file mode 100644
index 00000000..99925510
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_green_sticker.xml
@@ -0,0 +1,202 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_orange_cheer_left.xml b/app/src/main/res/drawable/ic_snail_orange_cheer_left.xml
new file mode 100644
index 00000000..d5a69e75
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_orange_cheer_left.xml
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_orange_cheer_right.xml b/app/src/main/res/drawable/ic_snail_orange_cheer_right.xml
new file mode 100644
index 00000000..0ee4a688
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_orange_cheer_right.xml
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_orange_hungry.xml b/app/src/main/res/drawable/ic_snail_orange_hungry.xml
new file mode 100644
index 00000000..40ebd3e7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_orange_hungry.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_orange_spoon_left.xml b/app/src/main/res/drawable/ic_snail_orange_spoon_left.xml
new file mode 100644
index 00000000..7abdb1f2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_orange_spoon_left.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_snail_orange_sticker.xml b/app/src/main/res/drawable/ic_snail_orange_sticker.xml
new file mode 100644
index 00000000..a85793dd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_snail_orange_sticker.xml
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_trash.xml b/app/src/main/res/drawable/ic_trash.xml
new file mode 100644
index 00000000..29fa5721
--- /dev/null
+++ b/app/src/main/res/drawable/ic_trash.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/img_service_intro_background.png b/app/src/main/res/drawable/img_service_intro_background.png
new file mode 100644
index 00000000..2d41e8c0
Binary files /dev/null and b/app/src/main/res/drawable/img_service_intro_background.png differ
diff --git a/app/src/main/res/drawable/img_service_intro_logo.png b/app/src/main/res/drawable/img_service_intro_logo.png
new file mode 100644
index 00000000..8955389c
Binary files /dev/null and b/app/src/main/res/drawable/img_service_intro_logo.png differ
diff --git a/app/src/main/res/drawable/selector_checkbox.xml b/app/src/main/res/drawable/selector_checkbox.xml
new file mode 100644
index 00000000..79da86f9
--- /dev/null
+++ b/app/src/main/res/drawable/selector_checkbox.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/selector_edittext_background.xml b/app/src/main/res/drawable/selector_edittext_background.xml
new file mode 100644
index 00000000..8433c68d
--- /dev/null
+++ b/app/src/main/res/drawable/selector_edittext_background.xml
@@ -0,0 +1,23 @@
+
+
+ -
+
+
-
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/selector_edittext_withdraw.xml b/app/src/main/res/drawable/selector_edittext_withdraw.xml
new file mode 100644
index 00000000..5d639d0a
--- /dev/null
+++ b/app/src/main/res/drawable/selector_edittext_withdraw.xml
@@ -0,0 +1,17 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/selector_tab_dot.xml b/app/src/main/res/drawable/selector_tab_dot.xml
new file mode 100644
index 00000000..6eb31cec
--- /dev/null
+++ b/app/src/main/res/drawable/selector_tab_dot.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_gray_radius_8.xml b/app/src/main/res/drawable/shape_border_gray_radius_8.xml
new file mode 100644
index 00000000..647973be
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_gray_radius_8.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_radius_12.xml b/app/src/main/res/drawable/shape_border_radius_12.xml
new file mode 100644
index 00000000..bb57fd05
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_radius_12.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_radius_16.xml b/app/src/main/res/drawable/shape_border_radius_16.xml
new file mode 100644
index 00000000..819d221e
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_radius_16.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_radius_4.xml b/app/src/main/res/drawable/shape_border_radius_4.xml
new file mode 100644
index 00000000..c0f94629
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_radius_4.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_radius_6.xml b/app/src/main/res/drawable/shape_border_radius_6.xml
new file mode 100644
index 00000000..5f2b856a
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_radius_6.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_border_radius_8.xml b/app/src/main/res/drawable/shape_border_radius_8.xml
new file mode 100644
index 00000000..a15ba5c8
--- /dev/null
+++ b/app/src/main/res/drawable/shape_border_radius_8.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_cursor.xml b/app/src/main/res/drawable/shape_cursor.xml
new file mode 100644
index 00000000..52cda949
--- /dev/null
+++ b/app/src/main/res/drawable/shape_cursor.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/shape_selected_dot.xml b/app/src/main/res/drawable/shape_selected_dot.xml
new file mode 100644
index 00000000..d002c89e
--- /dev/null
+++ b/app/src/main/res/drawable/shape_selected_dot.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_unselected_dot.xml b/app/src/main/res/drawable/shape_unselected_dot.xml
new file mode 100644
index 00000000..91ac5e51
--- /dev/null
+++ b/app/src/main/res/drawable/shape_unselected_dot.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/sign_keepgoeat.xml b/app/src/main/res/drawable/sign_keepgoeat.xml
new file mode 100644
index 00000000..0a207150
--- /dev/null
+++ b/app/src/main/res/drawable/sign_keepgoeat.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/snail_green_spoon.xml b/app/src/main/res/drawable/snail_green_spoon.xml
new file mode 100644
index 00000000..3ab71c7a
--- /dev/null
+++ b/app/src/main/res/drawable/snail_green_spoon.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/snail_orange_spoon.xml b/app/src/main/res/drawable/snail_orange_spoon.xml
new file mode 100644
index 00000000..e268f1ef
--- /dev/null
+++ b/app/src/main/res/drawable/snail_orange_spoon.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_account_info.xml b/app/src/main/res/layout/activity_account_info.xml
new file mode 100644
index 00000000..09144048
--- /dev/null
+++ b/app/src/main/res/layout/activity_account_info.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_archived_goal.xml b/app/src/main/res/layout/activity_archived_goal.xml
new file mode 100644
index 00000000..edb6875e
--- /dev/null
+++ b/app/src/main/res/layout/activity_archived_goal.xml
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_goal_detail.xml b/app/src/main/res/layout/activity_goal_detail.xml
new file mode 100644
index 00000000..05885c79
--- /dev/null
+++ b/app/src/main/res/layout/activity_goal_detail.xml
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_goal_setting.xml b/app/src/main/res/layout/activity_goal_setting.xml
new file mode 100644
index 00000000..f9fe4f3a
--- /dev/null
+++ b/app/src/main/res/layout/activity_goal_setting.xml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml
new file mode 100644
index 00000000..b02167e3
--- /dev/null
+++ b/app/src/main/res/layout/activity_home.xml
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_my.xml b/app/src/main/res/layout/activity_my.xml
new file mode 100644
index 00000000..25a4bfa5
--- /dev/null
+++ b/app/src/main/res/layout/activity_my.xml
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_onboarding.xml b/app/src/main/res/layout/activity_onboarding.xml
new file mode 100644
index 00000000..22a98d9e
--- /dev/null
+++ b/app/src/main/res/layout/activity_onboarding.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_service_intro.xml b/app/src/main/res/layout/activity_service_intro.xml
new file mode 100644
index 00000000..6f2776c3
--- /dev/null
+++ b/app/src/main/res/layout/activity_service_intro.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_sign.xml b/app/src/main/res/layout/activity_sign.xml
new file mode 100644
index 00000000..ecdf0006
--- /dev/null
+++ b/app/src/main/res/layout/activity_sign.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 00000000..58289b9f
--- /dev/null
+++ b/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_web_view.xml b/app/src/main/res/layout/activity_web_view.xml
new file mode 100644
index 00000000..612dd106
--- /dev/null
+++ b/app/src/main/res/layout/activity_web_view.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_withdraw.xml b/app/src/main/res/layout/activity_withdraw.xml
new file mode 100644
index 00000000..2a951a2b
--- /dev/null
+++ b/app/src/main/res/layout/activity_withdraw.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_bottom_goal_delete.xml b/app/src/main/res/layout/dialog_bottom_goal_delete.xml
new file mode 100644
index 00000000..1e48d723
--- /dev/null
+++ b/app/src/main/res/layout/dialog_bottom_goal_delete.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_bottom_goal_keep.xml b/app/src/main/res/layout/dialog_bottom_goal_keep.xml
new file mode 100644
index 00000000..e238b0df
--- /dev/null
+++ b/app/src/main/res/layout/dialog_bottom_goal_keep.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_bottom_home.xml b/app/src/main/res/layout/dialog_bottom_home.xml
new file mode 100644
index 00000000..7f3c9727
--- /dev/null
+++ b/app/src/main/res/layout/dialog_bottom_home.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_force_update.xml b/app/src/main/res/layout/dialog_force_update.xml
new file mode 100644
index 00000000..0f7460c6
--- /dev/null
+++ b/app/src/main/res/layout/dialog_force_update.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_goal_delete.xml b/app/src/main/res/layout/dialog_goal_delete.xml
new file mode 100644
index 00000000..767f92e0
--- /dev/null
+++ b/app/src/main/res/layout/dialog_goal_delete.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_logout.xml b/app/src/main/res/layout/dialog_logout.xml
new file mode 100644
index 00000000..d5f8ea23
--- /dev/null
+++ b/app/src/main/res/layout/dialog_logout.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_withdraw.xml b/app/src/main/res/layout/dialog_withdraw.xml
new file mode 100644
index 00000000..44c81d73
--- /dev/null
+++ b/app/src/main/res/layout/dialog_withdraw.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_add_goal.xml b/app/src/main/res/layout/item_add_goal.xml
new file mode 100644
index 00000000..3bbc496f
--- /dev/null
+++ b/app/src/main/res/layout/item_add_goal.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_archived_goal.xml b/app/src/main/res/layout/item_archived_goal.xml
new file mode 100644
index 00000000..fb80be52
--- /dev/null
+++ b/app/src/main/res/layout/item_archived_goal.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/item_goal_sticker.xml
similarity index 53%
rename from app/src/main/res/layout/activity_main.xml
rename to app/src/main/res/layout/item_goal_sticker.xml
index a9b8cabc..75ddef16 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/item_goal_sticker.xml
@@ -4,18 +4,21 @@
xmlns:tools="http://schemas.android.com/tools">
+ android:layout_height="wrap_content"
+ android:padding="3dp"
+ tools:background="@color/orange_50">
-
-
+ app:layout_constraintTop_toTopOf="parent"
+ tools:background="@drawable/ic_snail_orange_sticker" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_home_goal.xml b/app/src/main/res/layout/item_home_goal.xml
new file mode 100644
index 00000000..693e0276
--- /dev/null
+++ b/app/src/main/res/layout/item_home_goal.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_onboarding.xml b/app/src/main/res/layout/item_onboarding.xml
new file mode 100644
index 00000000..82079952
--- /dev/null
+++ b/app/src/main/res/layout/item_onboarding.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_withdraw.xml b/app/src/main/res/layout/item_withdraw.xml
new file mode 100644
index 00000000..27252a6b
--- /dev/null
+++ b/app/src/main/res/layout/item_withdraw.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/layout_archived_goal_header.xml b/app/src/main/res/layout/layout_archived_goal_header.xml
new file mode 100644
index 00000000..4d02661e
--- /dev/null
+++ b/app/src/main/res/layout/layout_archived_goal_header.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_eating_tag.xml b/app/src/main/res/layout/view_eating_tag.xml
new file mode 100644
index 00000000..79782e42
--- /dev/null
+++ b/app/src/main/res/layout/view_eating_tag.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_kge_snackbar.xml b/app/src/main/res/layout/view_kge_snackbar.xml
new file mode 100644
index 00000000..299b10ea
--- /dev/null
+++ b/app/src/main/res/layout/view_kge_snackbar.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_dummy.xml b/app/src/main/res/layout/view_toolbar.xml
similarity index 53%
rename from app/src/main/res/layout/activity_dummy.xml
rename to app/src/main/res/layout/view_toolbar.xml
index 07a3154a..4c4de785 100644
--- a/app/src/main/res/layout/activity_dummy.xml
+++ b/app/src/main/res/layout/view_toolbar.xml
@@ -6,28 +6,35 @@
+ name="title"
+ type="String" />
+ android:layout_height="wrap_content"
+ app:layout_constraintTop_toTopOf="parent">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat.xml b/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat.xml
new file mode 100644
index 00000000..6fa0b1ce
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat_round.xml
new file mode 100644
index 00000000..6fa0b1ce
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_keepgoeat_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index eca70cfe..c4a603d4 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index eca70cfe..c4a603d4 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_keepgoeat.png b/app/src/main/res/mipmap-hdpi/ic_keepgoeat.png
new file mode 100644
index 00000000..c1cba5c0
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_keepgoeat.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_keepgoeat_foreground.png b/app/src/main/res/mipmap-hdpi/ic_keepgoeat_foreground.png
new file mode 100644
index 00000000..9ac3b202
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_keepgoeat_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_keepgoeat_round.png b/app/src/main/res/mipmap-hdpi/ic_keepgoeat_round.png
new file mode 100644
index 00000000..51b6fa85
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_keepgoeat_round.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..dc34d0e9
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
deleted file mode 100644
index c209e78e..00000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..a0e1ca9c
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..ebe855ef
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
deleted file mode 100644
index b2dfe3d1..00000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_keepgoeat.png b/app/src/main/res/mipmap-mdpi/ic_keepgoeat.png
new file mode 100644
index 00000000..5d0d90bf
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_keepgoeat.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_keepgoeat_foreground.png b/app/src/main/res/mipmap-mdpi/ic_keepgoeat_foreground.png
new file mode 100644
index 00000000..c40601f5
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_keepgoeat_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_keepgoeat_round.png b/app/src/main/res/mipmap-mdpi/ic_keepgoeat_round.png
new file mode 100644
index 00000000..34d26a29
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_keepgoeat_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..acd377a1
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
deleted file mode 100644
index 4f0f1d64..00000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..723d9957
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..fd862dce
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
deleted file mode 100644
index 62b611da..00000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_keepgoeat.png b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat.png
new file mode 100644
index 00000000..5bc1e568
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_foreground.png
new file mode 100644
index 00000000..1b557869
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_round.png b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_round.png
new file mode 100644
index 00000000..8e77830a
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_keepgoeat_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..0a918b49
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
deleted file mode 100644
index 948a3070..00000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..60cf7bbf
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..89329f6c
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
deleted file mode 100644
index 1b9a6956..00000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat.png b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat.png
new file mode 100644
index 00000000..1809bc5d
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_foreground.png
new file mode 100644
index 00000000..8bba0ff1
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_round.png b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_round.png
new file mode 100644
index 00000000..fb5a7665
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_keepgoeat_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..7a3677d4
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
deleted file mode 100644
index 28d4b77f..00000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..6419ba1b
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..7a98e3b3
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9287f508..00000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat.png b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat.png
new file mode 100644
index 00000000..eefa927b
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_foreground.png
new file mode 100644
index 00000000..44671e5b
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_round.png
new file mode 100644
index 00000000..d68aaa00
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_keepgoeat_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..16ec9039
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
deleted file mode 100644
index aa7d6427..00000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..c235540d
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..183a2cad
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9126ae37..00000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/raw/home_background.json b/app/src/main/res/raw/home_background.json
new file mode 100644
index 00000000..653fba59
--- /dev/null
+++ b/app/src/main/res/raw/home_background.json
@@ -0,0 +1 @@
+{"v":"5.10.1","fr":60,"ip":0,"op":85,"w":360,"h":245,"nm":"homeBackgroundImage_0_and.png 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[68,61,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[57.485,57.485,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[11.303,11.303],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.349,-10.349],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"boom_41","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"boom_40","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"boom_39","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":135,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"boom_38","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"boom_37","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":225,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"boom_36","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"boom_35","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":315,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"boom_34","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[0]},{"t":57.4,"s":[100]}],"ix":11},"r":{"a":0,"k":360,"ix":10},"p":{"a":0,"k":[268.185,202.467,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":55.8,"s":[102.458,102.458,100]},{"t":74.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42.2,"s":[0]},{"t":73.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40.6,"s":[0]},{"t":71.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":39,"op":92,"st":39,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"round_5","parent":1,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":69,"s":[39]},{"t":72,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[268.939,202.259,0],"ix":2,"l":2},"a":{"a":0,"k":[-2,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":33,"s":[31.68,31.68,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":72,"s":[292.769,292.769,100]},{"t":83.4,"s":[210.767,210.767,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[27.438,27.438],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":40,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":54,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.281,3.219],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":33,"op":92,"st":33,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"star_4","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":47,"s":[100]},{"t":52,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[273.072,279.393,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[137.738,137.738,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.5,-55.5],[-3.5,35.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[49]},{"t":40,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[49]},{"t":44,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":14,"op":92,"st":14,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[68,61,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[57.485,57.485,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[11.303,11.303],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.349,-10.349],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"boom_33","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"boom_32","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"boom_31","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":135,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"boom_30","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"boom_29","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":225,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"boom_28","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"boom_27","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":315,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"boom_26","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":36,"s":[0]},{"t":50.4,"s":[100]}],"ix":11},"r":{"a":0,"k":360,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":48.8,"s":[102.458,102.458,100]},{"t":67.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35.2,"s":[0]},{"t":66.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.6,"s":[0]},{"t":64.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":32,"op":85,"st":32,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"round_4","parent":12,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":56,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[39]},{"t":65,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-33.746,-11.708,0],"ix":2,"l":2},"a":{"a":0,"k":[-2,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[31.68,31.68,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":65,"s":[292.769,292.769,100]},{"t":76.4,"s":[210.767,210.767,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[27.438,27.438],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":40,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":64,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.281,3.219],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":26,"op":85,"st":26,"ct":1,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"star_3","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[100]},{"t":45,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.614,65.425,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[137.738,137.738,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.5,-55.5],[-3.5,35.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[49]},{"t":33,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[49]},{"t":37,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":7,"op":85,"st":7,"ct":1,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[325.5,82.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[78.706,78.706,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[11.303,11.303],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.349,-10.349],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"boom_25","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"boom_24","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"boom_23","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":135,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"boom_22","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"boom_21","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":225,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"boom_20","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"boom_19","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":315,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":31,"ty":4,"nm":"boom_18","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":34.4,"s":[100]}],"ix":11},"r":{"a":0,"k":360,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":16.8,"s":[67.503,67.503,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":32.8,"s":[102.458,102.458,100]},{"t":51.2,"s":[136.89,136.89,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":19.2,"s":[0]},{"t":50.4,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17.6,"s":[0]},{"t":48.8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":16,"op":85,"st":16,"ct":1,"bm":0},{"ddd":0,"ind":32,"ty":4,"nm":"round_3","parent":23,"sr":0.8,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[98]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":23,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":46,"s":[39]},{"t":49,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-33.746,-11.708,0],"ix":2,"l":2},"a":{"a":0,"k":[-2,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[31.68,31.68,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":49,"s":[292.769,292.769,100]},{"t":60.4,"s":[210.767,210.767,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[27.438,27.438],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":54,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":52,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.281,3.219],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":82,"st":10,"ct":1,"bm":0},{"ddd":0,"ind":33,"ty":4,"nm":"star_2","parent":23,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[100]},{"t":29,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.614,65.425,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[137.738,137.738,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.5,-55.5],[-3.5,35.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[49]},{"t":28,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[49]},{"t":32,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":-9,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/res/raw/home_snail.json b/app/src/main/res/raw/home_snail.json
new file mode 100644
index 00000000..ca274807
--- /dev/null
+++ b/app/src/main/res/raw/home_snail.json
@@ -0,0 +1 @@
+{"v":"5.10.1","fr":60,"ip":0,"op":85,"w":140,"h":140,"nm":"snail_orange_cheer 2","ddd":0,"assets":[{"id":"comp_0","nm":"snail_orange_cheer","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":0.9,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[129,52.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[72.602,72.602,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[11.303,11.303],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":0,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.349,-10.349],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"boom_17","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"boom_16","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"boom_15","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":135,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"boom_14","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"boom_13","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":225,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"boom_12","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"boom_11","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":315,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"boom_10","parent":1,"sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33.5,"s":[0]},{"t":49.7,"s":[100]}],"ix":11},"r":{"a":0,"k":360,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29.9,"s":[67.5,67.5,100]},{"t":47.9,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.552144667682,1,0.813283823051,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32.6,"s":[0]},{"t":67.7,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30.8,"s":[0]},{"t":65.9,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":85,"st":29,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"round_2","sr":0.9,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60.999,"s":[100]},{"t":64.1,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[104.5,44.5,0],"ix":2,"l":2},"a":{"a":0,"k":[-2,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[23,23,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":64.1,"s":[167.904,167.904,100]},{"t":76.7,"s":[153.02,153.02,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[27.438,27.438],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":28,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.997341978784,0.892892156863,1,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.281,3.219],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":85,"st":20,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":3,"nm":"โฝ Group","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75.265,75,0],"ix":2,"l":2},"a":{"a":0,"k":[74.583,62.727,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"particle_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[114.755,35.363,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.776,-1.894],[0,0],[0,0],[0,0],[-2.403,-0.439],[0,0],[0,0]],"o":[[-2.507,-0.669],[0,0],[0,0],[0,0],[1.637,-1.804],[0,0],[0,0],[0,0]],"v":[[3.827,1.705],[-3.131,3.697],[-3.131,3.69],[-4.44,-0.97],[-4.064,-1.381],[2.427,-3.582],[3.159,-3.449],[4.44,1.865]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.709803938866,0.674509823322,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"particle_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[21.158,62.503,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.591,0.084],[0,0],[0,0],[0,0],[1.386,2.006],[0,0],[0,0]],"o":[[1.302,2.243],[0,0],[0,0],[0,0],[-2.438,0.118],[0,0],[0,0],[0,0]],"v":[[-1.581,-3.608],[4.743,-0.098],[4.75,-0.098],[2.382,4.122],[1.825,4.15],[-4.325,1.114],[-4.75,0.501],[-1.901,-4.159]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.709803938866,0.674509823322,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"particle_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[73.931,64.461,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.591,0.084],[0,0],[0,0],[0,0],[1.386,2.006],[0,0],[0,0]],"o":[[1.302,2.243],[0,0],[0,0],[0,0],[-2.438,0.118],[0,0],[0,0],[0,0]],"v":[[-1.581,-3.608],[4.743,-0.098],[4.75,-0.098],[2.382,4.122],[1.825,4.15],[-4.325,1.114],[-4.75,0.501],[-1.901,-4.159]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.596078455448,0.549019634724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"particle_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[24.15,31.677,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.211,-0.104],[0,0],[0,0],[0,0],[1.546,2.591],[0,0],[0,0]],"o":[[1.428,2.876],[0,0],[0,0],[0,0],[-3.023,-0.049],[0,0],[0,0],[0,0]],"v":[[-1.647,-4.583],[5.882,0.265],[5.889,0.272],[2.622,5.286],[1.933,5.272],[-5.415,1.031],[-5.889,0.244],[-1.995,-5.286]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.596078455448,0.549019634724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"particle_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50.642,43.465,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.104,3.211],[0,0],[0,0],[0,0],[2.486,-1.713],[0,0],[0,0]],"o":[[2.779,-1.609],[0,0],[0,0],[0,0],[0.146,3.016],[0,0],[0,0],[0,0]],"v":[[-4.459,1.954],[-0.113,-5.875],[-0.127,-5.875],[5.097,-2.943],[5.131,-2.253],[1.377,5.352],[0.625,5.875],[-5.142,2.351]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.807843148708,0.505882382393,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"particle_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[68.784,15.37,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.11,0.878],[0,0],[0,0],[0,0],[1.769,1.219],[0,0],[0,0]],"o":[[1.776,1.442],[0,0],[0,0],[0,0],[-1.964,0.857],[0,0],[0,0],[0,0]],"v":[[-2.493,-2.742],[3.81,-1.829],[3.81,-1.822],[3.183,2.384],[2.73,2.579],[-3.273,2.001],[-3.81,1.632],[-2.925,-3.097]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.784313738346,0.337254911661,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"cheer_2","parent":28,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-7.302,-4.357,0],"ix":2,"l":2},"a":{"a":0,"k":[10,-10,0],"ix":1,"l":2},"s":{"a":0,"k":[90,90,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.089,0.146],[-1.254,-1.86],[0,0],[0.536,-2.187],[-1.073,-1.295],[-0.369,-0.077],[0,0],[0.634,1.414],[0.049,0.334],[0,0],[0,0],[0,0],[-0.501,2.124],[-0.286,0.627],[0,0],[0.404,-3.106],[-0.021,-0.467],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.358,1.553],[-0.592,0.954],[2.814,-0.174],[0.279,0.021],[0,0],[-1.915,0.926],[-0.696,0.759],[1.24,1.811],[0.118,0.32],[0,0],[-1.79,0.237]],"o":[[2.25,-0.153],[0,0],[1.901,2.821],[-0.759,3.092],[0.362,0.432],[0,0],[-0.474,-0.209],[-0.188,-0.418],[0,0],[0,0],[0,0],[-0.23,-1.198],[0.202,-0.857],[0,0],[-1.08,0.989],[-0.063,0.529],[0,0],[0,0],[0,0],[0,0],[0,0],[1.17,-0.857],[0.961,-1.093],[-1.024,1.114],[-0.299,0.021],[0,0],[1.045,-0.063],[1.839,-0.891],[-0.55,-0.014],[-0.153,-0.223],[0,0],[1.066,0.383],[2.591,-0.348]],"v":[[5.417,-13.3],[11.393,-10.264],[11.407,-10.257],[11.804,-1.314],[10.71,5.303],[11.957,5.992],[9.366,10.652],[6.991,8.374],[6.664,7.232],[5.619,7.901],[6.19,11.188],[1.558,12.449],[1.649,7.288],[2.408,5.059],[1.823,5.595],[-1.638,11.815],[-1.701,13.312],[-6.681,12.268],[-4.027,6.459],[-4.94,5.86],[-8.701,10.38],[-12.009,6.334],[-8.102,2.754],[-5.789,-0.367],[-11.668,2.788],[-12.531,2.788],[-11.709,-3.173],[-7.008,-4.392],[-3.247,-7.192],[-7.551,-9.107],[-7.969,-9.915],[-4.313,-12.005],[0.089,-11.475]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.588235318661,0.498039245605,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"cheer_1","parent":29,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-8.562,-5.959,0],"ix":2,"l":2},"a":{"a":0,"k":[6,-10,0],"ix":1,"l":2},"s":{"a":0,"k":[90,90,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.839,0.383],[-1.344,-1.497],[0,0],[0.209,-2.013],[-1.114,-1.017],[-0.334,-0.028],[0,0],[0.738,1.184],[0.084,0.293],[0,0],[0,0],[0,0],[-0.181,1.95],[-0.174,0.592],[0,0],[-0.028,-2.814],[-0.077,-0.418],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.017,1.553],[-0.411,0.926],[2.479,-0.501],[0.258,-0.021],[0,0],[-1.588,1.059],[-0.522,0.759],[1.323,1.456],[0.146,0.272],[0,0],[-1.56,0.432]],"o":[[1.985,-0.418],[0,0],[2.034,2.271],[-0.293,2.842],[0.376,0.341],[0,0],[-0.453,-0.132],[-0.216,-0.348],[0,0],[0,0],[0,0],[-0.348,-1.038],[0.07,-0.787],[0,0],[-0.836,1.017],[0,0.474],[0,0],[0,0],[0,0],[0,0],[0,0],[0.933,-0.905],[0.717,-1.093],[-0.766,1.114],[-0.265,0.049],[0,0],[0.926,-0.181],[1.518,-1.017],[-0.488,0.056],[-0.16,-0.174],[0,0],[0.989,0.216],[2.264,-0.634]],"v":[[2.894,-12.216],[8.584,-10.259],[8.591,-10.252],[10.047,-2.354],[9.893,3.663],[11.084,4.123],[9.357,8.587],[6.961,6.853],[6.529,5.878],[5.687,6.602],[6.599,9.451],[2.636,11.144],[2.079,6.547],[2.476,4.471],[2.023,5.021],[-0.282,10.983],[-0.157,12.321],[-4.712,12.007],[-3.068,6.519],[-3.953,6.094],[-6.738,10.579],[-10.179,7.396],[-7.149,3.733],[-5.478,0.668],[-10.311,4.2],[-11.084,4.304],[-11.084,-1.101],[-7.052,-2.765],[-4.057,-5.718],[-8.117,-6.888],[-8.584,-7.55],[-5.596,-9.862],[-1.619,-9.932]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.588235318661,0.498039245605,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":21,"ty":3,"nm":"โฝ Group 2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.106,69.501,0],"ix":2,"l":2},"a":{"a":0,"k":[65.06,55.953,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"eye_2","parent":30,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.964,-15.717,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[1.351,0.55],[-0.23,0.564],[0,0],[-1.351,-0.55],[0.299,-0.738]],"o":[[-1.351,-0.55],[0,0],[0.286,-0.703],[1.351,0.55],[-0.418,1.024]],"v":[[-0.364,0.835],[-2.454,-1.025],[-2.454,-1.032],[0.346,-1.06],[2.436,0.96]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[1.218,0.741],[-0.212,0.519],[0,0],[-1.237,-0.522],[0.277,-0.679]],"o":[[-1.147,-0.698],[0,0],[0.552,-1.309],[1.455,0.615],[-0.385,0.942]],"v":[[-1.412,2.024],[-2.472,-0.723],[-2.472,-0.729],[0.91,-2.078],[2.027,1.104]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[{"i":[[1.218,0.741],[-0.212,0.519],[0,0],[-1.237,-0.522],[0.277,-0.679]],"o":[[-1.147,-0.698],[0,0],[0.552,-1.309],[1.455,0.615],[-0.385,0.942]],"v":[[-1.412,2.024],[-2.472,-0.723],[-2.472,-0.729],[0.91,-2.078],[2.027,1.104]],"c":true}]},{"t":48,"s":[{"i":[[1.351,0.55],[-0.23,0.564],[0,0],[-1.351,-0.55],[0.299,-0.738]],"o":[[-1.351,-0.55],[0,0],[0.286,-0.703],[1.351,0.55],[-0.418,1.024]],"v":[[-0.364,0.835],[-2.454,-1.025],[-2.454,-1.032],[0.346,-1.06],[2.436,0.96]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921574354,0.372549027205,0.368627458811,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"eye_1","parent":30,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-47.734,-15.612,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[-1.198,0.488],[0.202,0.501],[0,0],[1.198,-0.495],[-0.265,-0.655]],"o":[[1.198,-0.488],[0,0],[-0.251,-0.62],[-1.198,0.495],[0.369,0.912]],"v":[[0.321,0.743],[2.181,-0.914],[2.181,-0.921],[-0.305,-0.942],[-2.165,0.855]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[-1.564,0.58],[0.361,0.886],[0,0],[1.785,-0.836],[-0.265,-0.655]],"o":[[1.408,-0.522],[0,0],[-0.327,-0.732],[-1.174,0.55],[0.369,0.912]],"v":[[1.134,2.118],[2.181,-0.914],[2.181,-0.921],[-1.118,-1.817],[-2.165,0.855]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":34,"s":[{"i":[[-1.564,0.58],[0.361,0.886],[0,0],[1.785,-0.836],[-0.265,-0.655]],"o":[[1.408,-0.522],[0,0],[-0.327,-0.732],[-1.174,0.55],[0.369,0.912]],"v":[[1.134,2.118],[2.181,-0.914],[2.181,-0.921],[-1.118,-1.817],[-2.165,0.855]],"c":true}]},{"t":48,"s":[{"i":[[-1.198,0.488],[0.202,0.501],[0,0],[1.198,-0.495],[-0.265,-0.655]],"o":[[1.198,-0.488],[0,0],[-0.251,-0.62],[-1.198,0.495],[0.369,0.912]],"v":[[0.321,0.743],[2.181,-0.914],[2.181,-0.921],[-0.305,-0.942],[-2.165,0.855]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921574354,0.372549027205,0.368627458811,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Vector","parent":30,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-21.365,-10.39,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.043,0],[0,1.9],[3.043,0],[0,-1.9]],"o":[[3.043,0],[0,-1.9],[-3.043,0],[0,1.9]],"v":[[0,3.441],[5.509,0],[0,-3.441],[-5.509,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.666666686535,0.57647061348,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Vector","parent":30,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.699,-10.822,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.7,0],[0,1.281],[1.7,0],[0,-1.281]],"o":[[1.7,0],[0,-1.281],[-1.7,0],[0,1.281]],"v":[[0,2.319],[3.078,0],[0,-2.319],[-3.078,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.666666686535,0.57647061348,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Vector","parent":30,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-38.031,-7.883,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.481,2.382],[0.425,0],[0,0],[-0.084,-0.411],[-3.106,0]],"o":[[0.084,-0.411],[0,0],[-0.418,0],[0.481,2.389],[3.106,0]],"v":[[6.171,-1.699],[5.537,-2.507],[-5.537,-2.507],[-6.171,-1.699],[0,2.507]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921574354,0.372549027205,0.368627458811,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"hand_2","parent":21,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[6]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":31,"s":[-3]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[6]},{"t":65,"s":[-3]}],"ix":10},"p":{"a":0,"k":[56.935,71.222,0],"ix":2,"l":2},"a":{"a":0,"k":[7,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.466,1.609],[0.738,-1.282],[-0.752,-1.08],[-4.437,-1.811],[0,0]],"o":[[0,0],[-2.793,0],[-1.128,-0.738],[-0.669,1.163],[3.044,4.367],[0,0],[0,0]],"v":[[5.305,-4.71],[5.124,-4.71],[-2.879,-7.155],[-6.138,-6.2],[-5.992,-2.391],[5.444,7.047],[6.601,7.52]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":7,"k":{"a":0,"k":[0.089,0.98,0.902,0.792,0.25,0.98,0.896,0.78,0.411,0.98,0.89,0.769,0.636,0.98,0.842,0.741,0.86,0.98,0.794,0.714,0.93,0.99,0.804,0.711,1,1,0.813,0.708,0.089,0,0.25,0.11,0.411,0.22,0.636,0.525,0.86,0.83,0.93,0.915,1,1],"ix":9}},"s":{"a":0,"k":[6.601,-0.002],"ix":5},"e":{"a":0,"k":[-6.598,-0.002],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"hand_1","parent":21,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":31,"s":[-5]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[10]},{"t":65,"s":[-3]}],"ix":10},"p":{"a":0,"k":[13.601,73.702,0],"ix":2,"l":2},"a":{"a":0,"k":[7,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.466,1.609],[0.738,-1.282],[-0.752,-1.08],[-4.437,-1.811],[0,0]],"o":[[0,0],[-2.793,0],[-1.128,-0.738],[-0.669,1.163],[3.044,4.367],[0,0],[0,0]],"v":[[5.305,-4.71],[5.124,-4.71],[-2.879,-7.155],[-6.138,-6.2],[-5.992,-2.391],[5.444,7.047],[6.601,7.52]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.98,0.902,0.792,0.096,0.982,0.894,0.794,0.193,0.984,0.886,0.796,0.596,0.992,0.874,0.79,1,1,0.861,0.783,0,0,0.096,0.5,0.193,1,0.596,1,1,1],"ix":9}},"s":{"a":0,"k":[6.608,-0.002],"ix":5},"e":{"a":0,"k":[-6.591,-0.002],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"body","parent":21,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64.278,65.132,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":14,"s":[98,104,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":27,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":40,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":54,"s":[98,104,100]},{"t":67,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[7.682,0.501],[4.611,2.584],[0,0],[1.616,12.739],[0,0],[0,6.38],[-5.3,4.297],[0.299,1.351],[0,0],[-1.658,1.191],[-1.867,-1.637],[-5.349,-0.898],[0,0],[0,0],[0,0],[0,0],[0,0],[-3.462,3.462],[0,0],[-0.258,-3.58],[0.348,-2.013],[0,0],[-0.425,-1.685],[-0.146,-0.641],[-1.344,-3.594],[-0.341,-2.863],[-9.827,-1.867],[-1.003,-0.195],[-4.054,-3.51],[0,0],[0.947,-2.835],[3.099,0.313],[0,0],[13.714,-3.204]],"o":[[-5.279,-0.348],[0,0],[-10.134,-7.877],[0,0],[-5.091,-4.269],[0,-6.38],[0.209,-1.358],[0,0],[-0.348,-2.013],[2.013,-1.449],[4.081,3.58],[0,0],[0,0],[0.007,0],[0,0],[0,0],[4.827,-0.815],[0,0],[1.651,-1.651],[0.348,1.574],[0,0],[-0.376,1.692],[0.153,0.641],[1.226,2.709],[1.017,2.695],[1.156,9.73],[1.045,0.195],[5.265,1.038],[0,0],[2.479,1.672],[-0.989,2.953],[0,0],[-14.02,-1.414],[-4.464,1.045]],"v":[[-25.794,46.575],[-40.81,42.089],[-40.824,42.089],[-57.191,7.836],[-53.974,11.549],[-57.972,-1.434],[-51.007,-29.112],[-51.132,-33.207],[-52.107,-38.883],[-49.962,-44.121],[-43.332,-43.801],[-28.907,-36.947],[-27.055,-36.627],[-27.062,-36.627],[-27.048,-36.634],[-27.055,-36.634],[-23.524,-37.226],[-10.785,-43.794],[-8.612,-45.967],[-1.682,-43.181],[-2.002,-38.883],[-2.977,-33.207],[-2.908,-28.074],[-2.462,-26.159],[1.215,-17.961],[3.145,-9.569],[21.218,10.135],[24.29,10.72],[38.512,17.657],[55.13,32.046],[57.728,39.672],[50.742,44.193],[37.432,42.848],[-4.454,45.551]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,0.969,0.89,0.5,0.99,0.926,0.841,1,0.98,0.883,0.792],"ix":9}},"s":{"a":0,"k":[-20.951,4.441],"ix":5},"e":{"a":0,"k":[28.254,4.441],"ix":6},"t":2,"h":{"a":0,"k":0,"ix":7},"a":{"a":0,"k":0,"ix":8},"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.111,0.705],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":31,"ty":4,"nm":"back_4","parent":33,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-12.935,24.072,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.31,-10.935],[-22.656,-11.896],[0,0],[-6.31,10.935],[22.155,12.794]],"o":[[-6.31,10.935],[0,0],[6.624,3.482],[6.31,-10.935],[-22.155,-12.794]],"v":[[-40.098,-21.891],[-11.41,21.068],[-11.41,21.068],[40.136,24.432],[11.448,-18.527]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":11,"k":{"a":0,"k":[0,0.937,0.565,0.439,0.045,0.912,0.524,0.418,0.09,0.886,0.482,0.396,0.14,0.869,0.449,0.378,0.19,0.851,0.416,0.361,0.255,0.837,0.392,0.349,0.32,0.824,0.369,0.337,0.41,0.816,0.355,0.329,0.5,0.808,0.341,0.322,0.75,0.806,0.339,0.322,1,0.804,0.337,0.322],"ix":9}},"s":{"a":0,"k":[-15.647,-0.018],"ix":5},"e":{"a":0,"k":[70.134,-5.084],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":32,"ty":4,"nm":"back_3","parent":33,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[3.096,-2.073,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.074,3.455],[-15.88,-9.173],[0,0],[-4.827,-16.597],[2.528,-4.019],[0.536,-0.85],[20.219,11.673],[15.664,-2.082],[-0.369,0.592]],"o":[[14.793,-1.024],[0,0],[19.606,11.318],[-1.351,4.325],[-0.578,0.912],[-4.423,-17.092],[-17.301,-9.988],[0.355,-0.564],[2.995,-4.764]],"v":[[-36.906,-35.89],[10.733,-23.841],[10.747,-23.841],[48.691,20.831],[42.889,33.403],[41.218,36.049],[2.849,-10.169],[-48.691,-21.828],[-47.604,-23.555]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.937,0.565,0.439,0.285,0.927,0.451,0.38,0.57,0.918,0.337,0.322,0.785,0.927,0.451,0.38,1,0.937,0.565,0.439],"ix":9}},"s":{"a":0,"k":[-48.698,0],"ix":5},"e":{"a":0,"k":[48.67,0],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":33,"ty":4,"nm":"back_2","parent":21,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":27,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":54,"s":[-4]},{"t":67,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[70.93,52.773,0],"to":[0.583,-0.5,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":14,"s":[74.43,49.773,0],"to":[0,0,0],"ti":[0.583,-0.5,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":27,"s":[70.93,52.773,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":40,"s":[70.93,52.773,0],"to":[0.583,-0.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":54,"s":[74.43,50.773,0],"to":[0,0,0],"ti":[0.583,-0.333,0]},{"t":67,"s":[70.93,52.773,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-50.251,-31.961],[-15.727,24.983],[0,0],[24.983,15.727],[15.727,-24.983]],"o":[[40.793,25.944],[0,0],[15.733,-24.99],[-24.99,-15.733],[-15.727,24.99]],"v":[[-11.37,31.705],[45.971,31.329],[45.964,31.329],[29.207,-42.393],[-44.516,-25.636]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":7,"k":{"a":0,"k":[0,0.937,0.784,0.718,0.182,0.937,0.62,0.558,0.365,0.937,0.455,0.399,0.477,0.937,0.434,0.378,0.589,0.937,0.412,0.357,0.784,0.937,0.547,0.457,0.98,0.937,0.682,0.557],"ix":9}},"s":{"a":0,"k":[-54.19,0.002],"ix":5},"e":{"a":0,"k":[54.189,0.002],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":34,"ty":4,"nm":"back_1","parent":33,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[30.365,-36.361,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.885,-0.773],[0,0],[0,0],[0,0],[0,0],[0.808,1.644],[13.045,2.02]],"o":[[0,0],[0,0],[0,0],[0,0],[1.316,-1.282],[-5.356,-12.063],[-1.163,-0.181]],"v":[[-13.242,-14.432],[-18.577,-9.779],[-18.584,-9.772],[11.093,15.413],[17.305,9.367],[18.148,4.471],[-10.01,-15.365]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":7,"k":{"a":0,"k":[0,0.937,0.784,0.718,0.182,0.937,0.62,0.558,0.365,0.937,0.455,0.399,0.477,0.937,0.434,0.378,0.589,0.937,0.412,0.357,0.784,0.937,0.547,0.457,0.98,0.937,0.682,0.557],"ix":9}},"s":{"a":0,"k":[-18.584,0.001],"ix":5},"e":{"a":0,"k":[18.584,0.001],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":35,"ty":4,"nm":"boom_9","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":360,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":36,"ty":4,"nm":"boom_8","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":315,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":37,"ty":4,"nm":"boom_7","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":38,"ty":4,"nm":"boom_6","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":225,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":39,"ty":4,"nm":"boom_5","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":40,"ty":4,"nm":"boom_4","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":135,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":41,"ty":4,"nm":"boom_3","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":42,"ty":4,"nm":"boom_2","parent":43,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":28,"s":[100]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[-34.5,-11.5,0],"ix":2,"l":2},"a":{"a":0,"k":[26,-5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":6,"s":[67.5,67.5,100]},{"t":26,"s":[102.455,102.455,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[26,-5],[26,-35]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.862545955882,0.862545955882,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.403921598547,0.372549019608,0.36862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"t":48,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"t":46,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":43,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[11.303,11.303],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.937255021638,0.494118006089,0.415686005237,1],"ix":4},"o":{"a":0,"k":0,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.349,-10.349],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":5,"op":85,"st":5,"ct":1,"bm":0},{"ddd":0,"ind":44,"ty":4,"nm":"round_1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[55]},{"t":41,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[41,64.5,0],"ix":2,"l":2},"a":{"a":0,"k":[-2,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[23,23,100]},{"t":41,"s":[227.439,227.439,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[27.438,27.438],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":28,"ix":4},"w":{"a":0,"k":6,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.281,3.219],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":45,"ty":4,"nm":"snail_orange_cheer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75,75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[-100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[150,150],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"snail_orange_cheer","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":85,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"snail_orange_cheer","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[70,70,0],"ix":2,"l":2},"a":{"a":0,"k":[75,75,0],"ix":1,"l":2},"s":{"a":0,"k":[-94,94,100],"ix":6,"l":2}},"ao":0,"w":150,"h":150,"ip":0,"op":85,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 78d150ed..0968afce 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -9,6 +9,7 @@
#FFFFFFFF
+ #FFF6F2
#FFECE5
#FFD8CC
#FFCDBD
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..56c79535
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,15 @@
+
+
+ 4dp
+ 8dp
+ 10dp
+ 12dp
+ 14dp
+ 16dp
+ 20dp
+ 24dp
+ 36dp
+
+
+ 48dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 94ddbc75..3ca535ff 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,169 @@
KeepGoEat
upload
+ 1.0.0
+ Keepgo2at@gmail.com
+ market://details?id=
+
+
+ ํต๊ณ ์
+ ์๋ฃ
+ ๋ ๋จน๊ธฐ
+ ๋ ๋จน๊ธฐ
+ ์๋์ค
+ %s ๋ ๋จน๊ธฐ
+ %s ๋ ๋จน๊ธฐ
+ ์ทจ์
+ ๋ค
+ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ฃผ์ธ์.
+
+
+ ์นด์นด์คํก ๋ก๊ทธ์ธ
+ ๋ค์ด๋ฒ ๋ก๊ทธ์ธ
+ ์์ต๊ด ๊ด๋ฆฌ,
+ ๊ฐ์ด ์ฒ์ฒํ ์์ํด๋ณผ๊น์?\n๋จน๋ ์ฌ๋ฏธ๋ ์ธ์ ๋ ์์คํ๋๊น!
+ ์๋ ๋ก๊ทธ์ธ์ด ๋ง๋ฃ๋์์ต๋๋ค.
+ ๋ก๊ทธ์ธ ๋์์ต๋๋ค.
+ ๋ก๊ทธ์ธ์ ์คํจํ์์ต๋๋ค.
+
+
+ ๋์ ๋ชฉํ
+ %s %s
+ ์ง๋๋ฌ %s ๋
+ ์ด๋ฒ๋ฌ %s ๋
+ ๋จน์
+ ์ฐธ์
+ ๋ชฉํ๊ฐ ์ญ์ ๋์์ต๋๋ค.
+ ๋ชฉํ๊ฐ ๋ณด๊ด๋์์ต๋๋ค.
+
+
+ ์ค๋ ์์ต๊ด ๋ชฉํ
+
+ ์ค๋๋ ์ ๋จน์๋์?
+ ์ค๋๋ ํด๋์ด์!
+ ์ค๋๋ ์ ์ฐธ์๋์?
+ ์ค๋๋ ์ฐธ์์ด์!
+
+ ์ผ ํด๋์ด์.
+
+ ๋ ๋ค๋ฅธ ๋์ ์ ์ํ์๋์?
+ 2๊ฐ์ ๋ชฉํ๋ฅผ ๋ ์ ํ ์ ์์ด์.
+ 1๊ฐ์ ๋ชฉํ๋ฅผ ๋ ์ ํ ์ ์์ด์.
+ 3๊ฐ์ ๋ชฉํ๊น์ง ๋์์ ์งํํ ์ ์์ด์.
+
+ ์์ง ๋ชฉํ๋ฅผ ์ ํ์ง ์์์ด์.
+ ์๋ก์ด ๋ชฉํ๋ฅผ ์ถ๊ฐํด ๋ณด์ธ์.
+
+ ๋ชฉํ ์ถ๊ฐํ๊ธฐ
+
+ ๋ ๊น๋ํฝ, ๋ฉ์ง ๋ฌํฝ...โจ\n๋ด๊ฐ ์ธ์์ ์ง๋ฐฐํ๋ค...!!
+
+
+ ๊ฑด๊ฐํ ์์์ ๋ ๋จน์ด๋ณผ๊น?
+ ์ ์ข์ ์์ต๊ด์ ์ค์ฌ๊ฐ๋ณด์!
+
+
+ ๋ชฉํ๋ฅผ ๋ณด๊ดํ์๊ฒ ์ด์?
+ ๋ฌ์ฑ์ ์๋ฃํ ๋ชฉํ๋ ๋ณด๊ดํด์ ๋ชจ์๋ณผ ์ ์์ด์.
+ ์๋ชป๋ ๋ชฉํ์ธ๊ฐ์? ์ญ์ ํ๊ธฐ
+ ๋ชฉํ ๋ณด๊ดํ๊ธฐ
+
+
+ ์ญ์ ํ ๋ชฉํ๋ ๋ณต๊ตฌํ ์ ์์ด์.
+ ์ญ์ ํ์๊ฒ ์ด์?
+ ๋ค, ์ญ์ ํ ๋์
+
+
+ ๋ชฉํ ์
๋ ฅ
+ ๋์ ๋ชฉํ๋ฅผ ์
๋ ฅํด ๋ณผ๊น์?
+ ex) ๋ฌผ
+ ex) ์ปคํผ
+ ๋ชฉํ๋ ์ต์ 1๊ธ์ ์ด์ ์
๋ ฅํด์ฃผ์ธ์.
+ ํ๊ธ, ์๋ฌธ, ์ซ์๋ง ์
๋ ฅ ๊ฐ๋ฅํฉ๋๋ค.
+ (%d/15)
+ ๋ชฉํ ๋ฌ์ฑ ๊ธฐ์ค์ ์ธ์๋ณผ๊น์?
+ ๋์๊ฒ ๋ง๋ ๋ฌ์ฑ ๊ธฐ์ค์ ์ธ์์.
+ ex) ํ๋ฃจ์ 2L์ฉ ๋ง์๊ธฐ
+ ex) ์์นจ์ ๋ฑ 1์๋ง ๋ง์๊ธฐ
+ (%d/20)
+ ๋ชฉํ๊ฐ ์์ ๋์์ต๋๋ค.
+ ๋ชฉํ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
+
+
+ ์ฐจ๊ทผ์ฐจ๊ทผ ์์ต๊ด ๋ชฉํ๋ฅผ ์ธ์๋ณด์ธ์.
+ ๊ฑด๊ฐํ ์์ต๊ด์ ํ์์ฑ์ ๋๋ผ์
จ๋์?\n์ด์ ๋ ์กฐ๊ธ์ฉ ๋ ๋จน๊ณ , ๋ ๋จน์ผ๋ฉฐ ๊ท ํ์ ๋ง์ถฐ์.
+ ์กฐ๊ธ ๋ ์ค๋ช
ํด์ฃผ์ธ์!
+ ์ฐ๋ฆฌ๋ ๊ฐ์ด ํด๋ผ ๊ฑฐ์์.
+ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ ๋ ์ด๋ฉด ํต๊ณ ์์ ์ฐพ์์\n๋ฌ์ฑ ๋ฒํผ์ ๋๋ฌ์ฃผ์ธ์.
+ ๋งค์ผ ๊ธฐ๋ก์ ์คํจํ๋ฉด ์ด์ฉ์ฃ ?
+ ์๋ฒฝํ์ง ์์๋ ๊ด์ฐฎ์์.
+ ๋
ธ๋ ฅํ ๋ ๋ค์ ๋นํ์์ด ์ฑ์์ง ๊ฑฐ์์.\n์ฑ์ทจ์ ์ฆ๊ฑฐ์๊ณผ ๋ฟ๋ฏํจ์ด ์ค๋กฏ์ด ๋จ์์.
+ KEEP GO EAT ์์ํ๊ธฐ
+ ๊ฑด๋๋ฐ๊ธฐ
+
+
+ ์ ์ฒด
+ ๋ง์ดํ์ด์ง
+ ๋ณด๊ดํ ๋ชฉํ
+ ์ด ๋ฌ์ฑ์ผ
+ ์งํ๊ธฐ๊ฐ
+ %s. %s. %s ~ %s. %s. %s
+ ๋ก๊ทธ์์
+ ํํดํ๊ธฐ
+ ๋ฌธ์ ๋ฐ ํผ๋๋ฐฑ
+ ๋ฌธ์ํ๊ธฐ
+ ๋ฆฌ๋ทฐ ๋จ๊ธฐ๊ธฐ
+ ์ฑ ์ ๋ณด
+ ์๋น์ค ์๊ฐ
+ ๋ฒ์ ์ ๋ณด
+ ์ฝ๊ด ๋ฐ ์ ์ฑ
+ ์๋น์ค ์ด์ฉ์ฝ๊ด
+ ๊ฐ์ธ์ ๋ณด์ฒ๋ฆฌ๋ฐฉ์นจ
+
+ ๊ณ์ ์ ๋ณด
+ ๋ก๊ทธ์์ ํ์๊ฒ ์ด์?
+ ๊ทธ๋์์ ๊ธฐ๋ก์ ์ฌ๋ผ์ง์ง ์์ผ๋\n์์ฌํ๊ณ ๋ค๋
์ค์ธ์.
+ ๋ก๊ทธ์์ ๋์์ต๋๋ค.
+ ๋ก๊ทธ์์์ ์คํจํ์์ต๋๋ค.
+
+ ๋์ด์ ๊ธฐ๋กํ์ง ์๋ ๋ชฉํ๋ ๋ณด๊ดํด์.
+ ์งํํ์ง ์๋ ๋ชฉํ๊ฐ ์๊ธด๋ค๋ฉด,\n๊ทธ๋์์ ๋
ธ๋ ฅ์ ์ง์ฐ์ง ๋ง๊ณ ๋จ๊ฒจ๋ณด์ธ์.
+ ๋ชฉํ ๋ง๋ค๋ฌ ๊ฐ๊ธฐ
+ ์ญ์ ํ์๊ฒ ์ด์?
+ ์ญ์ ๋ ๋ชฉํ์ ๋ฌ์ฑ ๊ธฐ๋ก์\n๋ค์ ๋ณต๊ตฌํ ์ ์์ด์.
+
+ ํต๊ณ ์์\n์์์๋ ์นผ๋ก๋ฆฌ์ฒ๋ผ ๋ณต์กํ ๋ฐฉ๋ฒ ๋์ \n๊ฐ๋ณ๊ณ , ์ง์๊ฐ๋ฅํ ์์ต๊ด ๊ด๋ฆฌ๋ฅผ\n๋๊ธฐ ์ํด ํ์ํ์ด์.\n\n๋๋ฆฌ๊ฑฐ๋ ์ค์ด๊ณ ์ถ์ ์์ต๊ด ๋ชฉํ๋ฅผ ์ค์ ํ๊ณ ,\n๋ชฉํ๋ฅผ ๋ฌ์ฑํ ๋ ์ด๋ฉด ํต๊ณ ์์ ์ฐพ์์์ฃผ์ธ์.\n๊ฑด๊ฐํ ํ๋ฃจํ๋ฃจ๋ฅผ ๊ธฐ๋กํ ์ ์์ด์.\n\n๋งค์ผ ์๋ฒฝํ ์์ฌ๋ง์ ํ๊ธฐ๋ ์ด๋ ต์ฃ .\n๋์ ๊ฑด๊ฐํ์ง ์์ ์์์ ๋ ๋จน๊ณ ,\n๊ฑด๊ฐํ ์์์ ๋ ๋จน์ ๋ ์ ๋๋ ค๊ฐ๋ณผ๊น์?\n\n๋จน๋ ๊ฑด ์๋ ์ฆ๊ฑฐ์ด ์ผ์ด๋๊น.\n์๋ฒฝํ ์์ฌ์ ๋ํ ๋ถ๋ด ์์ด\nํต๊ณ ์์์ ๊ฑด๊ฐํ ์ฆ๊ฑฐ์์ ์์๋ณด์ธ์.
+ ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ
+
+ ํต๊ณ ์ ๋ฌธ์์ฌํญ
+ Device: %s %s\nApp version: %s\nOS Version: %d(%s)\n-------------\n๋ด์ฉ :
+
+ ๋ฆฌ๋ทฐ๋ฅผ ๋จ๊ฒจ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค.
+
+
+ ํํดํ๊ธฐ
+ ๊ทธ๋์ ํจ๊ป ํด์ ๊ธฐ๋ปค์ด์.
+ ๋ ๋ฌ๋ ์ด์ ๋ฅผ ๋ชจ๋ ์๋ ค์ฃผ์๋ฉด ๋ ๋์ ํต๊ณ ์์ด ๋ ๊ฒ์.
+
+ ์์ต๊ด ๊ด๋ฆฌ๋ฅผ ๊ทธ๋ง ๋์ด์.
+ ์์ฃผ ์ฌ์ฉํ์ง ์์์.
+ ์ฑ ์ค๋ฅ๊ฐ ์์ด์.
+ ์ฝํ
์ธ ๊ฐ ๋ง์กฑ์ค๋ฝ์ง ์์์.
+
+ ์ง์ ์
๋ ฅ
+ ๋ค๋ฅธ ์ด์ ๊ฐ ์๋ค๋ฉด ์๋ ค์ฃผ์ธ์.
+ ํํด ์ด์ ๋ฅผ ์์ฑํด์ฃผ์ธ์.
+
+ ํํด๋ ๋๋๋ฆด ์ ์์ด์.
+ ์ด ๊ณ์ ์์ ๋ง๋ ๋ชฉํ์\nํ๋ ๊ธฐ๋ก์ด ๋ชจ๋ ์ฌ๋ผ์ ธ์.
+ ํํด
+ ์ทจ์
+
+ ํ์ ํํด๊ฐ ์๋ฃ๋์์ต๋๋ค.
+ ํ์ ํํด์ ์คํจํ์์ต๋๋ค.
+
+
+ ์
๋ฐ์ดํธ ์๋ฆผ
+ ์
๋ฐ์ดํธ ํ๋ฌ๊ฐ๊ธฐ
+ ๋ ์ข์์ง ํต๊ณ ์ ์ฑ์ ์ฌ์ฉํ์๊ธฐ ์ํด์๋ ์๋ก์ด ๋ฒ์ %s์ผ๋ก ์
๋ฐ์ดํธ๊ฐ ํ์ํฉ๋๋ค. ํ์ฌ ๋ฒ์ ์ %s ์
๋๋ค.
\ No newline at end of file
diff --git a/app/src/main/res/values/text_appearance.xml b/app/src/main/res/values/text_appearance.xml
new file mode 100644
index 00000000..957b2c8b
--- /dev/null
+++ b/app/src/main/res/values/text_appearance.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index c989bc2d..3b5639e8 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,4 +1,4 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 932ffdc0..64d1389c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -10,6 +10,8 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
+
+ maven { url 'https://devrepo.kakao.com/nexus/content/groups/public/' }
}
}
rootProject.name = "KeepGoEat"