diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b5e7a5b6 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Ahn-seokjoo @jaeryo2357 @Sookhee diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 797761ab..1a9bf2e8 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -4,7 +4,7 @@ on: push: branches: [ "develop" ] pull_request: - branches: [ "develop" ] + branches: [ "develop", "refactor*", "fix*", "feat*", "feature*", "chore*", "test*" ] jobs: build: diff --git a/.gitignore b/.gitignore index a876adea..2f22f858 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,7 @@ obj/ .idea/gradle.xml .idea/jarRepositories.xml .idea/navEditor.xml +.idea/codeStyles/Project.xml # OS-specific files .DS_Store diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 9f503962..00000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 83771bc5..00000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 8fac0723..10f16f58 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { applicationId "com.mashup" minSdkVersion minVersion targetSdkVersion targetVersion - versionCode 20 - versionName "1.1.4" + versionCode 21 + versionName "1.2.0" testInstrumentationRunner "com.mashup.core.testing.MashUpTestRunner" vectorDrawables { @@ -98,6 +98,7 @@ dependencies { implementation project(":core:datastore") implementation project(":core:firebase") implementation project(":feature:setting") + implementation project(":feature:danggn") // ml Kit implementation "com.google.mlkit:barcode-scanning:$barcodeSacnnerVersion" @@ -140,4 +141,9 @@ dependencies { // coroutine test testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutineVersion" + + // flipper + implementation "com.facebook.flipper:flipper:$flipperVersion" + implementation "com.facebook.soloader:soloader:$soLoaderVersion" + implementation "com.facebook.flipper:flipper-network-plugin:$flipperVersion" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 30a92e8d..75d6841b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,18 @@ + + + + + + diff --git a/app/src/main/java/com/mashup/MashUpApplication.kt b/app/src/main/java/com/mashup/MashUpApplication.kt index cfb7483e..d8e18bb5 100644 --- a/app/src/main/java/com/mashup/MashUpApplication.kt +++ b/app/src/main/java/com/mashup/MashUpApplication.kt @@ -1,7 +1,25 @@ package com.mashup import android.app.Application +import com.facebook.flipper.android.AndroidFlipperClient +import com.facebook.flipper.android.utils.FlipperUtils +import com.facebook.flipper.plugins.inspector.DescriptorMapping +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin +import com.facebook.soloader.SoLoader +import com.mashup.di.NetworkModule import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class MashUpApplication : Application() +class MashUpApplication : Application() { + override fun onCreate() { + super.onCreate() + SoLoader.init(this, false) + + if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { + val client = AndroidFlipperClient.getInstance(this) + client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) + client.addPlugin(NetworkModule.flipperNetwork) + client.start() + } + } +} diff --git a/app/src/main/java/com/mashup/base/BaseActivity.kt b/app/src/main/java/com/mashup/base/BaseActivity.kt index c39a5780..0adeea57 100644 --- a/app/src/main/java/com/mashup/base/BaseActivity.kt +++ b/app/src/main/java/com/mashup/base/BaseActivity.kt @@ -4,6 +4,7 @@ import android.app.Dialog import android.os.Bundle import android.view.LayoutInflater import androidx.appcompat.app.AppCompatActivity +import androidx.core.os.bundleOf import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat @@ -12,7 +13,12 @@ import androidx.databinding.ViewDataBinding import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import com.mashup.constant.EXTRA_ACTIVITY_ENTER_TYPE import com.mashup.constant.EXTRA_ANIMATION +import com.mashup.core.common.constant.BAD_REQUEST +import com.mashup.core.common.constant.DISCONNECT_NETWORK +import com.mashup.core.common.constant.INTERNAL_SERVER_ERROR +import com.mashup.core.common.constant.UNAUTHORIZED import com.mashup.core.common.model.NavigationAnimationType import com.mashup.core.common.utils.ProgressbarUtil import com.mashup.core.common.utils.ToastUtil @@ -20,12 +26,9 @@ import com.mashup.core.common.utils.keyboard.RootViewDeferringInsetsCallback import com.mashup.core.common.widget.CommonDialog import com.mashup.network.NetworkStatusState import com.mashup.network.data.NetworkStatusDetector -import com.mashup.network.errorcode.BAD_REQUEST -import com.mashup.network.errorcode.DISCONNECT_NETWORK -import com.mashup.network.errorcode.INTERNAL_SERVER_ERROR -import com.mashup.network.errorcode.UNAUTHORIZED import com.mashup.ui.error.NetworkDisconnectActivity import com.mashup.ui.login.LoginActivity +import com.mashup.util.AnalyticsManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -179,4 +182,9 @@ abstract class BaseActivity : AppCompatActivity() { ) } } + + protected fun sendActivityEnterType(screenName: String) { + val type = intent.getStringExtra(EXTRA_ACTIVITY_ENTER_TYPE) ?: return + AnalyticsManager.addEvent(screenName, bundleOf("type" to type)) + } } diff --git a/app/src/main/java/com/mashup/base/BaseFragment.kt b/app/src/main/java/com/mashup/base/BaseFragment.kt index 79eccf8e..18017f9a 100644 --- a/app/src/main/java/com/mashup/base/BaseFragment.kt +++ b/app/src/main/java/com/mashup/base/BaseFragment.kt @@ -11,15 +11,15 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import com.mashup.core.common.constant.BAD_REQUEST +import com.mashup.core.common.constant.DISCONNECT_NETWORK +import com.mashup.core.common.constant.INTERNAL_SERVER_ERROR +import com.mashup.core.common.constant.UNAUTHORIZED import com.mashup.core.common.utils.ProgressbarUtil import com.mashup.core.common.utils.ToastUtil import com.mashup.core.common.widget.CommonDialog import com.mashup.network.NetworkStatusState import com.mashup.network.data.NetworkStatusDetector -import com.mashup.network.errorcode.BAD_REQUEST -import com.mashup.network.errorcode.DISCONNECT_NETWORK -import com.mashup.network.errorcode.INTERNAL_SERVER_ERROR -import com.mashup.network.errorcode.UNAUTHORIZED import com.mashup.ui.error.NetworkDisconnectActivity import com.mashup.ui.login.LoginActivity import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/com/mashup/constant/ExtraConstant.kt b/app/src/main/java/com/mashup/constant/ExtraConstant.kt index 69e84909..0db4f406 100644 --- a/app/src/main/java/com/mashup/constant/ExtraConstant.kt +++ b/app/src/main/java/com/mashup/constant/ExtraConstant.kt @@ -1,5 +1,6 @@ package com.mashup.constant +const val EXTRA_MAIN_TAB = "EXTRA_MAIN_TAB" const val EXTRA_LOGIN_TYPE = "EXTRA_MAIN_TYPE" const val EXTRA_TITLE_KEY = "EXTRA_TITLE_KEY" @@ -10,3 +11,9 @@ const val EXTRA_LOGOUT = "EXTRA_LOGOUT" const val EXTRA_WITH_DRAWL = "EXTRA_WITH_DRAWL" const val EXTRA_ANIMATION = "EXTRA_ANIMATION" + +const val EXTRA_LINK = "link" + +const val EXTRA_POPUP_KEY = "EXTRA_POPUP_KEY" + +const val EXTRA_ACTIVITY_ENTER_TYPE = "EXTRA_ACTIVITY_ENTER_TYPE" \ No newline at end of file diff --git a/app/src/main/java/com/mashup/constant/log/UserActionLogs.kt b/app/src/main/java/com/mashup/constant/log/UserActionLogs.kt index fb6e86f3..1edc9236 100644 --- a/app/src/main/java/com/mashup/constant/log/UserActionLogs.kt +++ b/app/src/main/java/com/mashup/constant/log/UserActionLogs.kt @@ -31,3 +31,9 @@ const val LOG_QR_TIME_FAIL = "qr_time_fail" const val LOG_QR_WRONG = "qr_wrong" const val LOG_DELETE_SUCCESS_USER = "delete_user_success" + +const val LOG_COMMON_POPUP_CONFIRM = "popup_new_confirm" +const val LOG_COMMON_POPUP_CANCEL = "popup_new_cancel" + +const val LOG_DANGGN = "danggn" +const val LOG_DANGGN_HELP = "danggn_help" \ No newline at end of file diff --git a/app/src/main/java/com/mashup/data/dto/AccessResponse.kt b/app/src/main/java/com/mashup/data/dto/AccessResponse.kt index 6e4dfc81..44150384 100644 --- a/app/src/main/java/com/mashup/data/dto/AccessResponse.kt +++ b/app/src/main/java/com/mashup/data/dto/AccessResponse.kt @@ -15,6 +15,8 @@ class AccessResponse( val platform: String, @field:Json(name = "token") val token: String, - @field:Json(name = "pushNotificationAgreed") - val pushNotificationAgreed: Boolean + @field:Json(name = "newsPushNotificationAgreed") + val pushNotificationAgreed: Boolean, + @field:Json(name = "danggnPushNotificationAgreed") + val danggnPushNotificationAgreed: Boolean ) diff --git a/app/src/main/java/com/mashup/data/dto/MemberInfoResponse.kt b/app/src/main/java/com/mashup/data/dto/MemberInfoResponse.kt index 54bdabad..b3d9ddb5 100644 --- a/app/src/main/java/com/mashup/data/dto/MemberInfoResponse.kt +++ b/app/src/main/java/com/mashup/data/dto/MemberInfoResponse.kt @@ -15,6 +15,8 @@ data class MemberInfoResponse( val name: String, @field:Json(name = "platform") val platform: String, - @field:Json(name = "pushNotificationAgreed") - val pushNotificationAgreed: Boolean + @field:Json(name = "newsPushNotificationAgreed") + val pushNotificationAgreed: Boolean, + @field:Json(name = "danggnPushNotificationAgreed") + val danggnPushNotificationAgreed: Boolean ) diff --git a/app/src/main/java/com/mashup/data/dto/PushNotificationRequest.kt b/app/src/main/java/com/mashup/data/dto/PushNotificationRequest.kt index c66b6ed0..a887ce18 100644 --- a/app/src/main/java/com/mashup/data/dto/PushNotificationRequest.kt +++ b/app/src/main/java/com/mashup/data/dto/PushNotificationRequest.kt @@ -5,6 +5,8 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) class PushNotificationRequest( - @field:Json(name = "pushNotificationAgreed") - val pushNotificationAgreed: Boolean + @field:Json(name = "newsPushNotificationAgreed") + val pushNotificationAgreed: Boolean, + @field:Json(name = "danggnPushNotificationAgreed") + val danggnPushNotificationAgreed: Boolean ) diff --git a/app/src/main/java/com/mashup/data/dto/StorageResponse.kt b/app/src/main/java/com/mashup/data/dto/StorageResponse.kt new file mode 100644 index 00000000..4fc1e554 --- /dev/null +++ b/app/src/main/java/com/mashup/data/dto/StorageResponse.kt @@ -0,0 +1,12 @@ +package com.mashup.data.dto + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class StorageResponse( + @field:Json(name = "keyString") + val keyString: String, + @field:Json(name = "valueMap") + val valueMap: Map +) diff --git a/app/src/main/java/com/mashup/data/repository/MemberRepository.kt b/app/src/main/java/com/mashup/data/repository/MemberRepository.kt index 81ea2913..966acfda 100644 --- a/app/src/main/java/com/mashup/data/repository/MemberRepository.kt +++ b/app/src/main/java/com/mashup/data/repository/MemberRepository.kt @@ -81,9 +81,13 @@ class MemberRepository @Inject constructor( return memberDao.deleteMember() } - suspend fun patchPushNotification(pushNotificationAgreed: Boolean): Response { + suspend fun patchPushNotification( + pushNotificationAgreed: Boolean, + danggnPushNotificationAgreed: Boolean + ): Response { val requestBody = PushNotificationRequest( - pushNotificationAgreed = pushNotificationAgreed + pushNotificationAgreed = pushNotificationAgreed, + danggnPushNotificationAgreed = danggnPushNotificationAgreed ) return memberDao.patchPushNotification(requestBody) diff --git a/app/src/main/java/com/mashup/data/repository/PopUpRepository.kt b/app/src/main/java/com/mashup/data/repository/PopUpRepository.kt new file mode 100644 index 00000000..8214761c --- /dev/null +++ b/app/src/main/java/com/mashup/data/repository/PopUpRepository.kt @@ -0,0 +1,23 @@ +package com.mashup.data.repository + +import com.mashup.network.Response +import com.mashup.network.dao.PopupDao +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class PopUpRepository @Inject constructor( + private val popupDao: PopupDao +) { + suspend fun patchPopupViewed(popupType: String): Response { + return popupDao.patchPopupViewed(popupType) + } + + suspend fun getPopupKeyList(): Response> { + return popupDao.getMembersPopupKeyList() + } + + suspend fun patchPopupDisabled(popupType: String): Response { + return popupDao.patchPopupDisabled(popupType) + } +} diff --git a/app/src/main/java/com/mashup/data/repository/StorageRepository.kt b/app/src/main/java/com/mashup/data/repository/StorageRepository.kt new file mode 100644 index 00000000..54d3bd3d --- /dev/null +++ b/app/src/main/java/com/mashup/data/repository/StorageRepository.kt @@ -0,0 +1,16 @@ +package com.mashup.data.repository + +import com.mashup.data.dto.StorageResponse +import com.mashup.network.Response +import com.mashup.network.dao.StorageDao +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class StorageRepository @Inject constructor( + private val storageDao: StorageDao +) { + suspend fun getStorage(key: String): Response { + return storageDao.getStorage(key) + } +} diff --git a/app/src/main/java/com/mashup/di/NetworkModule.kt b/app/src/main/java/com/mashup/di/NetworkModule.kt index 52cc7462..3ac645f9 100644 --- a/app/src/main/java/com/mashup/di/NetworkModule.kt +++ b/app/src/main/java/com/mashup/di/NetworkModule.kt @@ -1,15 +1,20 @@ package com.mashup.di +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin import com.mashup.BuildConfig.DEBUG_MODE import com.mashup.data.network.API_HOST import com.mashup.network.CustomDateAdapter import com.mashup.network.dao.AttendanceDao import com.mashup.network.dao.MemberDao +import com.mashup.network.dao.PopupDao import com.mashup.network.dao.ScheduleDao import com.mashup.network.dao.ScoreDao +import com.mashup.network.dao.StorageDao import com.mashup.network.interceptor.AuthInterceptor import com.mashup.network.interceptor.BaseInterceptor import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -26,28 +31,42 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module class NetworkModule { + companion object { + val flipperNetwork = NetworkFlipperPlugin() + } + @Provides @Singleton fun provideMoshi(): Moshi = Moshi.Builder() .add(Date::class.java, CustomDateAdapter().nullSafe()) + .addLast(KotlinJsonAdapterFactory()) .build() + @Provides + @Singleton + fun provideFlipperOkhttpInterceptor() = + FlipperOkhttpInterceptor(flipperNetwork) + @Provides @Singleton fun provideOkHttpClient( authInterceptor: AuthInterceptor, - baseInterceptor: BaseInterceptor + baseInterceptor: BaseInterceptor, + flipperInterceptor: FlipperOkhttpInterceptor, ): OkHttpClient { + val okHttpClient = OkHttpClient.Builder() .addInterceptor(authInterceptor) .addInterceptor(baseInterceptor) if (DEBUG_MODE) { - okHttpClient.addInterceptor( - HttpLoggingInterceptor().apply { - setLevel(HttpLoggingInterceptor.Level.BODY) - } - ) + okHttpClient + .addNetworkInterceptor(flipperInterceptor) + .addInterceptor( + HttpLoggingInterceptor().apply { + setLevel(HttpLoggingInterceptor.Level.BODY) + } + ) } return okHttpClient .readTimeout(10L, TimeUnit.SECONDS) @@ -99,4 +118,20 @@ class NetworkModule { ): ScoreDao { return retrofit.create() } + + @Provides + @Singleton + fun provideStorageDao( + retrofit: Retrofit + ): StorageDao { + return retrofit.create() + } + + @Provides + @Singleton + fun providePopupDao( + retrofit: Retrofit + ): PopupDao { + return retrofit.create() + } } diff --git a/app/src/main/java/com/mashup/network/dao/PopupDao.kt b/app/src/main/java/com/mashup/network/dao/PopupDao.kt new file mode 100644 index 00000000..d459540e --- /dev/null +++ b/app/src/main/java/com/mashup/network/dao/PopupDao.kt @@ -0,0 +1,21 @@ +package com.mashup.network.dao + +import com.mashup.network.Response +import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.Path + +interface PopupDao { + @PATCH("/api/v1/member-popups/{popupType}/last-viewed") + suspend fun patchPopupViewed( + @Path("popupType") popupType: String + ): Response + + @GET("/api/v1/member-popups") + suspend fun getMembersPopupKeyList(): Response> + + @PATCH("/api/v1/member-popups/{popupType}/disabled") + suspend fun patchPopupDisabled( + @Path("popupType") popupType: String + ): Response +} diff --git a/app/src/main/java/com/mashup/network/dao/StorageDao.kt b/app/src/main/java/com/mashup/network/dao/StorageDao.kt new file mode 100644 index 00000000..3c3c42af --- /dev/null +++ b/app/src/main/java/com/mashup/network/dao/StorageDao.kt @@ -0,0 +1,13 @@ +package com.mashup.network.dao + +import com.mashup.data.dto.StorageResponse +import com.mashup.network.Response +import retrofit2.http.GET +import retrofit2.http.Path + +interface StorageDao { + @GET("/api/v1/storage/key/{key}") + suspend fun getStorage( + @Path("key") key: String + ): Response +} diff --git a/app/src/main/java/com/mashup/network/interceptor/AuthInterceptor.kt b/app/src/main/java/com/mashup/network/interceptor/AuthInterceptor.kt index 85df3de9..b1c9ae68 100644 --- a/app/src/main/java/com/mashup/network/interceptor/AuthInterceptor.kt +++ b/app/src/main/java/com/mashup/network/interceptor/AuthInterceptor.kt @@ -1,7 +1,7 @@ package com.mashup.network.interceptor import com.mashup.datastore.data.repository.UserPreferenceRepository -import com.mashup.network.errorcode.UNAUTHORIZED +import com.mashup.core.common.constant.UNAUTHORIZED import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking diff --git a/app/src/main/java/com/mashup/util/MashUpFirebaseMessagingService.kt b/app/src/main/java/com/mashup/service/MashUpFirebaseMessagingService.kt similarity index 88% rename from app/src/main/java/com/mashup/util/MashUpFirebaseMessagingService.kt rename to app/src/main/java/com/mashup/service/MashUpFirebaseMessagingService.kt index a01306d5..d9ebc328 100644 --- a/app/src/main/java/com/mashup/util/MashUpFirebaseMessagingService.kt +++ b/app/src/main/java/com/mashup/service/MashUpFirebaseMessagingService.kt @@ -1,4 +1,4 @@ -package com.mashup.util +package com.mashup.service import android.app.NotificationChannel import android.app.NotificationManager @@ -16,8 +16,9 @@ import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.mashup.BuildConfig import com.mashup.R -import dagger.hilt.android.AndroidEntryPoint +import com.mashup.constant.EXTRA_LINK import com.mashup.ui.splash.SplashActivity +import dagger.hilt.android.AndroidEntryPoint import java.net.URL @AndroidEntryPoint @@ -40,13 +41,24 @@ class MashUpFirebaseMessagingService : FirebaseMessagingService() { if (title != null && body != null) { createNotificationChannel() - notifyPushMessage(title, body, imageUrl) + notifyPushMessage( + title = title, + body = body, + imageUrl = imageUrl, + data = message.data + ) } } - private fun notifyPushMessage(title: String, body: String, imageUrl: Uri?) { + private fun notifyPushMessage( + title: String, + body: String, + imageUrl: Uri?, + data: Map + ) { val splashIntent = Intent(this, SplashActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP + putExtra(EXTRA_LINK, data[EXTRA_LINK]) } val pendingIntent = PendingIntent.getActivity( diff --git a/app/src/main/java/com/mashup/service/PushLinkType.kt b/app/src/main/java/com/mashup/service/PushLinkType.kt new file mode 100644 index 00000000..6ab232cb --- /dev/null +++ b/app/src/main/java/com/mashup/service/PushLinkType.kt @@ -0,0 +1,15 @@ +package com.mashup.service + +enum class PushLinkType { + MAIN, // 기본 페이지 + QR, // QR 페이지 + DANGGN, // 당근 페이지 + MYPAGE, + UNKNOWN, + ; + + companion object { + fun getPushLinkType(type: String) = + values().find { it.name == type } ?: UNKNOWN + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceActivity.kt b/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceActivity.kt index 9df1c54e..30fec2e8 100644 --- a/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceActivity.kt +++ b/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceActivity.kt @@ -15,7 +15,7 @@ import com.mashup.core.common.model.NavigationAnimationType import com.mashup.core.ui.theme.MashUpTheme import com.mashup.data.model.PlatformInfo import com.mashup.databinding.ActivityCrewAttendanceBinding -import com.mashup.network.errorcode.SCHEDULE_NOT_FOUND +import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND import com.mashup.ui.attendance.crew.CrewAttendanceViewModel.Companion.EXTRA_PLATFORM_KEY import com.mashup.ui.attendance.crew.CrewAttendanceViewModel.Companion.EXTRA_SCHEDULE_ID import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceViewModel.kt b/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceViewModel.kt index 67dca571..741d7543 100644 --- a/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceViewModel.kt +++ b/app/src/main/java/com/mashup/ui/attendance/crew/CrewAttendanceViewModel.kt @@ -1,11 +1,11 @@ package com.mashup.ui.attendance.crew import androidx.lifecycle.SavedStateHandle -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.data.dto.PlatformAttendanceResponse import com.mashup.data.model.PlatformInfo import com.mashup.data.repository.AttendanceRepository -import com.mashup.network.errorcode.BAD_REQUEST +import com.mashup.core.common.constant.BAD_REQUEST import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceActivity.kt b/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceActivity.kt index 7884340e..0f8ef865 100644 --- a/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceActivity.kt +++ b/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceActivity.kt @@ -13,8 +13,8 @@ import com.mashup.core.common.model.NavigationAnimationType import com.mashup.core.ui.theme.MashUpTheme import com.mashup.data.model.PlatformInfo import com.mashup.databinding.ActivityPlatformAttendanceBinding -import com.mashup.network.errorcode.EVENT_NOT_FOUND -import com.mashup.network.errorcode.SCHEDULE_NOT_FOUND +import com.mashup.core.common.constant.EVENT_NOT_FOUND +import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND import com.mashup.ui.attendance.crew.CrewAttendanceActivity import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceViewModel.kt b/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceViewModel.kt index 8aeef089..aac42577 100644 --- a/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceViewModel.kt +++ b/app/src/main/java/com/mashup/ui/attendance/platform/PlatformAttendanceViewModel.kt @@ -3,7 +3,7 @@ package com.mashup.ui.attendance.platform import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.constant.EXTRA_SCHEDULE_ID import com.mashup.data.dto.TotalAttendanceResponse import com.mashup.data.repository.AttendanceRepository diff --git a/app/src/main/java/com/mashup/ui/danggn/DanggnInfoActivity.kt b/app/src/main/java/com/mashup/ui/danggn/DanggnInfoActivity.kt new file mode 100644 index 00000000..0c83d346 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/danggn/DanggnInfoActivity.kt @@ -0,0 +1,36 @@ +package com.mashup.ui.danggn + +import android.content.Context +import android.content.Intent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import com.mashup.R +import com.mashup.base.BaseActivity +import com.mashup.constant.EXTRA_ANIMATION +import com.mashup.core.common.model.NavigationAnimationType +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.databinding.ActivityDanggnInfoBinding +import com.mashup.feature.danggn.DanggnInfoScreen + +class DanggnInfoActivity : BaseActivity() { + override val layoutId: Int = R.layout.activity_danggn_info + + override fun initViews() { + super.initViews() + + viewBinding.shakeDanggnScreen.setContent { + MashUpTheme { + DanggnInfoScreen( + modifier = Modifier.fillMaxSize(), + onClickBackButton = { onBackPressed() }, + ) + } + } + } + + companion object { + fun newIntent(context: Context) = Intent(context, DanggnInfoActivity::class.java).apply { + putExtra(EXTRA_ANIMATION, NavigationAnimationType.SLIDE) + } + } +} diff --git a/app/src/main/java/com/mashup/ui/danggn/ShakeDanggnActivity.kt b/app/src/main/java/com/mashup/ui/danggn/ShakeDanggnActivity.kt new file mode 100644 index 00000000..4c92bec2 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/danggn/ShakeDanggnActivity.kt @@ -0,0 +1,78 @@ +package com.mashup.ui.danggn + +import android.content.Context +import android.content.Intent +import androidx.activity.viewModels +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import com.mashup.R +import com.mashup.base.BaseActivity +import com.mashup.constant.EXTRA_ACTIVITY_ENTER_TYPE +import com.mashup.constant.EXTRA_ANIMATION +import com.mashup.constant.log.LOG_DANGGN +import com.mashup.constant.log.LOG_DANGGN_HELP +import com.mashup.core.common.model.ActivityEnterType +import com.mashup.core.common.model.NavigationAnimationType +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.databinding.ActivityShakeDanggnBinding +import com.mashup.feature.danggn.DanggnUiState +import com.mashup.feature.danggn.DanggnViewModel +import com.mashup.feature.danggn.ShakeDanggnScreen +import com.mashup.feature.danggn.ranking.DanggnRankingViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.collectLatest + +@AndroidEntryPoint +class ShakeDanggnActivity : BaseActivity() { + override val layoutId: Int = R.layout.activity_shake_danggn + + private val viewModel: DanggnViewModel by viewModels() + private val rankingViewModel: DanggnRankingViewModel by viewModels() + + override fun initViews() { + super.initViews() + sendActivityEnterType(LOG_DANGGN) + + viewBinding.shakeDanggnScreen.setContent { + MashUpTheme { + ShakeDanggnScreen( + modifier = Modifier.fillMaxSize(), + viewModel = viewModel, + rankingViewModel = rankingViewModel, + onClickBackButton = { onBackPressed() }, + onClickDanggnInfoButton = { openDanggnInfoActivity() } + ) + } + } + } + + override fun initObserves() { + super.initObserves() + flowLifecycleScope { + viewModel.uiState.collectLatest { state -> + when (state) { + is DanggnUiState.Error -> { + handleCommonError(state.code) + } + else -> {} + } + } + } + } + + private fun openDanggnInfoActivity() { + sendActivityEnterType(LOG_DANGGN_HELP) + val intent = DanggnInfoActivity.newIntent(this) + startActivity(intent) + } + + companion object { + fun newIntent( + context: Context, + type: ActivityEnterType = ActivityEnterType.NORMAL + ) = Intent(context, ShakeDanggnActivity::class.java).apply { + putExtra(EXTRA_ANIMATION, NavigationAnimationType.SLIDE) + putExtra(EXTRA_ACTIVITY_ENTER_TYPE, type.name) + } + } +} diff --git a/app/src/main/java/com/mashup/ui/login/LoginActivity.kt b/app/src/main/java/com/mashup/ui/login/LoginActivity.kt index d816c0c9..dde927a6 100644 --- a/app/src/main/java/com/mashup/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/mashup/ui/login/LoginActivity.kt @@ -13,8 +13,8 @@ import com.mashup.constant.log.LOG_SIGN_UP import com.mashup.core.common.extensions.onThrottleFirstClick import com.mashup.core.common.model.Validation import com.mashup.databinding.ActivityLoginBinding -import com.mashup.network.errorcode.MEMBER_NOT_FOUND -import com.mashup.network.errorcode.MEMBER_NOT_MATCH_PASSWORD +import com.mashup.core.common.constant.MEMBER_NOT_FOUND +import com.mashup.core.common.constant.MEMBER_NOT_MATCH_PASSWORD import com.mashup.ui.main.MainActivity import com.mashup.ui.signup.SignUpActivity import com.mashup.util.AnalyticsManager diff --git a/app/src/main/java/com/mashup/ui/login/LoginViewModel.kt b/app/src/main/java/com/mashup/ui/login/LoginViewModel.kt index 40b18838..03e1f6e4 100644 --- a/app/src/main/java/com/mashup/ui/login/LoginViewModel.kt +++ b/app/src/main/java/com/mashup/ui/login/LoginViewModel.kt @@ -1,17 +1,17 @@ package com.mashup.ui.login -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.common.model.Validation import com.mashup.core.firebase.FirebaseRepository import com.mashup.core.model.Platform import com.mashup.data.repository.MemberRepository import com.mashup.datastore.data.repository.UserPreferenceRepository import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first -import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( @@ -69,6 +69,7 @@ class LoginViewModel @Inject constructor( response.data?.apply { userPreferenceRepository.updateUserPreference( + id = memberId, token = token, name = name, platform = Platform.getPlatform(platform), diff --git a/app/src/main/java/com/mashup/ui/main/MainActivity.kt b/app/src/main/java/com/mashup/ui/main/MainActivity.kt index 528e37d6..0a917bca 100644 --- a/app/src/main/java/com/mashup/ui/main/MainActivity.kt +++ b/app/src/main/java/com/mashup/ui/main/MainActivity.kt @@ -11,17 +11,24 @@ import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_ANIMATION import com.mashup.constant.EXTRA_LOGIN_TYPE +import com.mashup.constant.EXTRA_MAIN_TAB import com.mashup.core.common.extensions.onThrottleFirstClick import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.common.extensions.setStatusBarDarkTextColor +import com.mashup.core.common.model.ActivityEnterType import com.mashup.core.common.model.NavigationAnimationType +import com.mashup.core.common.utils.safeShow import com.mashup.databinding.ActivityMainBinding +import com.mashup.ui.danggn.ShakeDanggnActivity import com.mashup.ui.login.LoginType +import com.mashup.ui.main.model.MainPopupType import com.mashup.ui.main.model.MainTab +import com.mashup.ui.main.popup.MainBottomPopup import com.mashup.ui.qrscan.CongratsAttendanceScreen import com.mashup.ui.qrscan.QRScanActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch @AndroidEntryPoint class MainActivity : BaseActivity() { @@ -80,10 +87,36 @@ class MainActivity : BaseActivity() { override fun initObserves() { super.initObserves() flowLifecycleScope { - viewModel.mainTab.collectLatest { tab -> - navigationTab(tab) - setUIOfTab(tab) - updateStatusBarColor(tab) + launch { + viewModel.mainTab.collectLatest { tab -> + navigationTab(tab) + setUIOfTab(tab) + updateStatusBarColor(tab) + } + } + + launch { + viewModel.showPopupType.collectLatest { + MainBottomPopup.newInstance(it).safeShow(supportFragmentManager) + } + } + + launch { + viewModel.onClickPopupConfirm.collectLatest { popupType -> + when (popupType) { + MainPopupType.DANGGN -> { + viewModel.disablePopup(popupType) + startActivity( + ShakeDanggnActivity.newIntent( + context = this@MainActivity, + type = ActivityEnterType.POPUP + ) + ) + } + else -> { + } + } + } } } } @@ -150,10 +183,12 @@ class MainActivity : BaseActivity() { companion object { fun newIntent( context: Context, - loginType: LoginType + loginType: LoginType, + mainTab: MainTab = MainTab.EVENT ) = Intent(context, MainActivity::class.java).apply { putExtra(EXTRA_ANIMATION, NavigationAnimationType.PULL) putExtra(EXTRA_LOGIN_TYPE, loginType) + putExtra(EXTRA_MAIN_TAB, mainTab) } } } diff --git a/app/src/main/java/com/mashup/ui/main/MainViewModel.kt b/app/src/main/java/com/mashup/ui/main/MainViewModel.kt index 870415b9..c308f6e9 100644 --- a/app/src/main/java/com/mashup/ui/main/MainViewModel.kt +++ b/app/src/main/java/com/mashup/ui/main/MainViewModel.kt @@ -3,24 +3,29 @@ package com.mashup.ui.main import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle -import com.mashup.base.BaseViewModel import com.mashup.constant.EXTRA_LOGIN_TYPE +import com.mashup.constant.EXTRA_MAIN_TAB +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.model.Platform import com.mashup.data.repository.MemberRepository +import com.mashup.data.repository.PopUpRepository import com.mashup.datastore.data.repository.UserPreferenceRepository import com.mashup.ui.login.LoginType +import com.mashup.ui.main.model.MainPopupType import com.mashup.ui.main.model.MainTab import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow -import javax.inject.Inject +import kotlinx.coroutines.flow.asSharedFlow @HiltViewModel class MainViewModel @Inject constructor( private val memberRepository: MemberRepository, + private val popUpRepository: PopUpRepository, private val userPreferenceRepository: UserPreferenceRepository, savedStateHandle: SavedStateHandle ) : BaseViewModel() { @@ -31,13 +36,23 @@ class MainViewModel @Inject constructor( private val _onAttendance = MutableSharedFlow() val onAttendance: SharedFlow = _onAttendance - private val _successAttendance = MutableSharedFlow() - val successAttendance: SharedFlow = _successAttendance + private val _showPopupType = MutableSharedFlow() + val showPopupType: SharedFlow = _showPopupType.asSharedFlow() + + private val _onClickPopupConfirm = MutableSharedFlow() + val onClickPopupConfirm: SharedFlow = _onClickPopupConfirm.asSharedFlow() + init { savedStateHandle.get(EXTRA_LOGIN_TYPE)?.run { handleLoginType(this) } + + savedStateHandle.get(EXTRA_MAIN_TAB)?.run { + setMainTab(this) + } + + getMainPopup() } private val _mainTab = MutableStateFlow(MainTab.EVENT) @@ -49,7 +64,6 @@ class MainViewModel @Inject constructor( fun successAttendance() = mashUpScope { _isShowCongratsAttendanceScreen.value = true - _successAttendance.emit(Unit) delay(2000L) _isShowCongratsAttendanceScreen.value = false } @@ -80,6 +94,7 @@ class MainViewModel @Inject constructor( val result = memberRepository.getMember() if (result.isSuccess() && result.data != null) { userPreferenceRepository.updateUserPreference( + id = result.data.id, name = result.data.name, platform = Platform.getPlatform(result.data.platform), generationNumbers = result.data.generationNumbers, @@ -88,6 +103,28 @@ class MainViewModel @Inject constructor( } } + private fun getMainPopup() = mashUpScope { + val result = popUpRepository.getPopupKeyList() + if (result.isSuccess()) { + val popupType = + MainPopupType.getMainPopupType(result.data?.firstOrNull() ?: return@mashUpScope) + if (popupType == MainPopupType.UNKNOWN) return@mashUpScope + _showPopupType.emit(popupType) + } + } + + fun disablePopup(popupKey: MainPopupType) = mashUpScope { + if (popupKey == MainPopupType.UNKNOWN) return@mashUpScope + popUpRepository.patchPopupDisabled(popupKey.name) + } + + fun onClickPopup(popupKey: String) = mashUpScope { + val popupType = + MainPopupType.getMainPopupType(popupKey) + if (popupType == MainPopupType.UNKNOWN) return@mashUpScope + _onClickPopupConfirm.emit(popupType) + } + override fun handleErrorCode(code: String) { } } diff --git a/app/src/main/java/com/mashup/ui/main/model/MainPopupEntity.kt b/app/src/main/java/com/mashup/ui/main/model/MainPopupEntity.kt new file mode 100644 index 00000000..666c1582 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/main/model/MainPopupEntity.kt @@ -0,0 +1,9 @@ +package com.mashup.ui.main.model + +data class MainPopupEntity( + val title: String, + val description: String, + val imageResName: String, + val leftButtonText: String, + val rightButtonText: String +) diff --git a/app/src/main/java/com/mashup/ui/main/model/MainPopupType.kt b/app/src/main/java/com/mashup/ui/main/model/MainPopupType.kt new file mode 100644 index 00000000..63c65b4e --- /dev/null +++ b/app/src/main/java/com/mashup/ui/main/model/MainPopupType.kt @@ -0,0 +1,11 @@ +package com.mashup.ui.main.model + +enum class MainPopupType { + DANGGN, UNKNOWN; + + companion object { + fun getMainPopupType(type: String): MainPopupType { + return MainPopupType.values().find { it.name == type } ?: UNKNOWN + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopup.kt b/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopup.kt new file mode 100644 index 00000000..63967f1e --- /dev/null +++ b/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopup.kt @@ -0,0 +1,248 @@ +package com.mashup.ui.main.popup + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Divider +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat +import androidx.core.os.bundleOf +import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.mashup.constant.EXTRA_POPUP_KEY +import com.mashup.constant.log.LOG_COMMON_POPUP_CANCEL +import com.mashup.constant.log.LOG_COMMON_POPUP_CONFIRM +import com.mashup.core.common.utils.getDrawableResIdByName +import com.mashup.core.ui.colors.Gray500 +import com.mashup.core.ui.colors.Gray950 +import com.mashup.core.ui.colors.White +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Body4 +import com.mashup.core.ui.typography.SubTitle1 +import com.mashup.core.ui.widget.ButtonStyle +import com.mashup.core.ui.widget.MashUpButton +import com.mashup.ui.main.MainViewModel +import com.mashup.ui.main.model.MainPopupEntity +import com.mashup.ui.main.model.MainPopupType +import com.mashup.util.AnalyticsManager +import dagger.hilt.android.AndroidEntryPoint + + +@AndroidEntryPoint +class MainBottomPopup : BottomSheetDialogFragment() { + + private val mainViewModel: MainViewModel by activityViewModels() + + companion object { + fun newInstance(popupType: MainPopupType) = MainBottomPopup().apply { + arguments = bundleOf( + EXTRA_POPUP_KEY to popupType.name + ) + } + } + + + private val viewModel: MainBottomPopupViewModel by viewModels() + + private val behavior: BottomSheetBehavior? + get() { + val bottomSheet = + dialog?.findViewById(com.google.android.material.R.id.design_bottom_sheet) + return bottomSheet?.let { + BottomSheetBehavior.from(bottomSheet) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewModel.patchPopupViewed() + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + + setContent { + MashUpTheme { + MainBottomPopupScreen( + viewModel = viewModel, + onClickLeftButton = { + AnalyticsManager.addEvent(LOG_COMMON_POPUP_CANCEL, bundleOf("key" to viewModel.popupKey)) + dismiss() + }, + onClickRightButton = { + mainViewModel.onClickPopup(viewModel.popupKey ?: "") + AnalyticsManager.addEvent(LOG_COMMON_POPUP_CONFIRM, bundleOf("key" to viewModel.popupKey)) + dismiss() + } + ) + } + } + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val bottomSheetDialog = dialog as? BottomSheetDialog + bottomSheetDialog?.findViewById(com.google.android.material.R.id.design_bottom_sheet) + ?.run { + setBackgroundColor( + ContextCompat.getColor( + requireContext(), + android.R.color.transparent + ) + ) + } + + addGlobalLayoutListener(view) + } + + private fun addGlobalLayoutListener(view: View) { + view.viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + if (this@MainBottomPopup.view?.height == 0) return + view.viewTreeObserver.removeOnGlobalLayoutListener(this) + behavior?.state = BottomSheetBehavior.STATE_EXPANDED + behavior?.peekHeight = this@MainBottomPopup.view?.height ?: 0 + } + }) + } +} + +@Composable +fun MainBottomPopupScreen( + viewModel: MainBottomPopupViewModel, + onClickLeftButton: () -> Unit = {}, + onClickRightButton: () -> Unit = {} +) { + val uiState: MainBottomPopupUiState by viewModel.uiState + + (uiState as? MainBottomPopupUiState.Success)?.let { + MainBottomPopupContent( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(20.dp), + mainPopupEntity = it.mainPopupEntity, + onClickLeftButton = onClickLeftButton, + onClickRightButton = onClickRightButton + ) + } +} + + +@Composable +fun MainBottomPopupContent( + mainPopupEntity: MainPopupEntity, + modifier: Modifier = Modifier, + onClickLeftButton: () -> Unit = {}, + onClickRightButton: () -> Unit = {} +) { + Column( + modifier = modifier + .background( + color = White, + shape = RoundedCornerShape(20.dp) + ) + ) { + Divider( + modifier = Modifier + .width(24.dp) + .align(CenterHorizontally) + .padding(vertical = 10.dp), + color = Color(0xFFD9D9D9), + thickness = 3.dp + ) + + Text( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp) + .padding(horizontal = 20.dp), + text = mainPopupEntity.title, + style = SubTitle1, + color = Gray950, + textAlign = TextAlign.Center + ) + + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 8.dp), + text = mainPopupEntity.description, + style = Body4, + color = Gray500, + textAlign = TextAlign.Center + ) + + val context = LocalContext.current + val imageResId = remember(mainPopupEntity.imageResName) { + context.getDrawableResIdByName(mainPopupEntity.imageResName) + } + Image( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 16.dp), + painter = painterResource(id = imageResId), + contentDescription = null + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + MashUpButton( + modifier = Modifier.wrapContentWidth(), + text = mainPopupEntity.leftButtonText, + buttonStyle = ButtonStyle.INVERSE, + onClick = onClickLeftButton + ) + + MashUpButton( + modifier = Modifier.weight(1f), + text = mainPopupEntity.rightButtonText, + buttonStyle = ButtonStyle.PRIMARY, + onClick = onClickRightButton + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopupViewModel.kt b/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopupViewModel.kt new file mode 100644 index 00000000..482c37da --- /dev/null +++ b/app/src/main/java/com/mashup/ui/main/popup/MainBottomPopupViewModel.kt @@ -0,0 +1,58 @@ +package com.mashup.ui.main.popup + +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.SavedStateHandle +import com.mashup.constant.EXTRA_POPUP_KEY +import com.mashup.core.common.base.BaseViewModel +import com.mashup.data.repository.PopUpRepository +import com.mashup.data.repository.StorageRepository +import com.mashup.ui.main.model.MainPopupEntity +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class MainBottomPopupViewModel @Inject constructor( + private val storageRepository: StorageRepository, + private val popUpRepository: PopUpRepository, + savedStateHandle: SavedStateHandle +) : BaseViewModel() { + val popupKey = savedStateHandle.get(EXTRA_POPUP_KEY) + + private val _uiState = mutableStateOf(MainBottomPopupUiState.Loading) + val uiState: State = _uiState + + init { + getStorage() + } + + private fun getStorage() = mashUpScope { + if (popupKey.isNullOrBlank()) return@mashUpScope + val result = storageRepository.getStorage(popupKey) + + if (result.isSuccess()) { + _uiState.value = MainBottomPopupUiState.Success( + MainPopupEntity( + title = result.data?.valueMap?.get("title") ?: "", + description = result.data?.valueMap?.get("subtitle") ?: "", + imageResName = result.data?.valueMap?.get("imageName") ?: "", + leftButtonText = result.data?.valueMap?.get("leftButtonTitle") ?: "", + rightButtonText = result.data?.valueMap?.get("rightButtonTitle") ?: "" + ) + ) + } + } + + fun patchPopupViewed() = mashUpScope { + if (popupKey.isNullOrBlank()) return@mashUpScope + popUpRepository.patchPopupViewed(popupKey) + } +} + +sealed interface MainBottomPopupUiState { + object Loading : MainBottomPopupUiState + + data class Success( + val mainPopupEntity: MainPopupEntity + ) : MainBottomPopupUiState +} \ No newline at end of file diff --git a/app/src/main/java/com/mashup/ui/mypage/MyPageViewModel.kt b/app/src/main/java/com/mashup/ui/mypage/MyPageViewModel.kt index 1ccd5de5..74d71c2b 100644 --- a/app/src/main/java/com/mashup/ui/mypage/MyPageViewModel.kt +++ b/app/src/main/java/com/mashup/ui/mypage/MyPageViewModel.kt @@ -2,7 +2,7 @@ package com.mashup.ui.mypage import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.data.dto.ScoreHistoryResponse import com.mashup.data.repository.MyPageRepository import com.mashup.datastore.data.repository.UserPreferenceRepository diff --git a/app/src/main/java/com/mashup/ui/qrscan/QRScanActivity.kt b/app/src/main/java/com/mashup/ui/qrscan/QRScanActivity.kt index 5182a73f..6b4c8d39 100644 --- a/app/src/main/java/com/mashup/ui/qrscan/QRScanActivity.kt +++ b/app/src/main/java/com/mashup/ui/qrscan/QRScanActivity.kt @@ -29,7 +29,7 @@ import com.mashup.network.errorcode.ATTENDANCE_CODE_INVALID import com.mashup.network.errorcode.ATTENDANCE_CODE_NOT_FOUND import com.mashup.network.errorcode.ATTENDANCE_TIME_BEFORE import com.mashup.network.errorcode.ATTENDANCE_TIME_OVER -import com.mashup.network.errorcode.MEMBER_NOT_FOUND +import com.mashup.core.common.constant.MEMBER_NOT_FOUND import com.mashup.ui.qrscan.camera.CameraManager import com.mashup.util.AnalyticsManager import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/mashup/ui/qrscan/QRScanViewModel.kt b/app/src/main/java/com/mashup/ui/qrscan/QRScanViewModel.kt index 3dcf8743..be70daf5 100644 --- a/app/src/main/java/com/mashup/ui/qrscan/QRScanViewModel.kt +++ b/app/src/main/java/com/mashup/ui/qrscan/QRScanViewModel.kt @@ -1,7 +1,7 @@ package com.mashup.ui.qrscan import androidx.lifecycle.viewModelScope -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.data.repository.AttendanceRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt index 4b7ca19d..54ac5b23 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt @@ -13,7 +13,6 @@ import androidx.viewpager2.widget.ViewPager2 import com.mashup.R import com.mashup.base.BaseFragment import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL -import com.mashup.constant.log.LOG_SCHEDULE_LIST_REFRESH import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM import com.mashup.core.common.extensions.fromHtml import com.mashup.core.common.extensions.gone @@ -21,7 +20,9 @@ import com.mashup.core.common.extensions.onThrottleFirstClick import com.mashup.core.common.extensions.visible import com.mashup.databinding.FragmentScheduleBinding import com.mashup.ui.attendance.platform.PlatformAttendanceActivity +import com.mashup.ui.danggn.ShakeDanggnActivity import com.mashup.ui.main.MainViewModel +import com.mashup.ui.main.model.MainPopupType import com.mashup.ui.schedule.adapter.OnItemClickListener import com.mashup.ui.schedule.adapter.ScheduleViewPagerAdapter import com.mashup.ui.schedule.detail.ScheduleDetailActivity @@ -78,6 +79,7 @@ class ScheduleFragment : BaseFragment() { super.initViews() initSwipeRefreshLayout() initViewPager() + initButtons() } private fun initSwipeRefreshLayout() { @@ -121,6 +123,15 @@ class ScheduleFragment : BaseFragment() { offscreenPageLimit = 4 } } + + private fun initButtons() { + viewBinding.btnDanggnEntryPoint.onThrottleFirstClick(lifecycleScope) { + mainViewModel.disablePopup(MainPopupType.DANGGN) + startActivity( + ShakeDanggnActivity.newIntent(requireContext()) + ) + } + } override fun initObserves() { flowViewLifecycleScope { diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt index f7704115..9bbe0a54 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt @@ -1,6 +1,6 @@ package com.mashup.ui.schedule -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.data.dto.ScheduleResponse import com.mashup.data.dto.SchedulesProgress import com.mashup.data.repository.AttendanceRepository diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt index 4fe7eef4..e62a84c0 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt @@ -7,7 +7,7 @@ import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_SCHEDULE_ID import com.mashup.databinding.ActivityScheduleDetailBinding -import com.mashup.network.errorcode.SCHEDULE_NOT_FOUND +import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt index 6ef61e2d..a476690d 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt @@ -1,7 +1,7 @@ package com.mashup.ui.schedule.detail import androidx.lifecycle.SavedStateHandle -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.constant.EXTRA_SCHEDULE_ID import com.mashup.data.dto.EventResponse import com.mashup.data.repository.ScheduleRepository diff --git a/app/src/main/java/com/mashup/ui/setting/PushActivity.kt b/app/src/main/java/com/mashup/ui/setting/PushActivity.kt new file mode 100644 index 00000000..0c2d6250 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/setting/PushActivity.kt @@ -0,0 +1,62 @@ +package com.mashup.ui.setting + +import android.content.Context +import android.content.Intent +import androidx.activity.viewModels +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.mashup.R +import com.mashup.base.BaseActivity +import com.mashup.constant.EXTRA_ANIMATION +import com.mashup.core.common.model.NavigationAnimationType +import com.mashup.core.model.data.local.UserPreference +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.databinding.ActivitySettingBinding +import com.mashup.feature.setting.ui.push.PushScreen +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class PushActivity : BaseActivity() { + + private val viewModel: SettingViewModel by viewModels() + + override fun initViews() { + super.initViews() + + viewBinding.settingScreen.setContent { + MashUpTheme { + val userPreference by viewModel.userPreference.collectAsState( + initial = UserPreference.getDefaultInstance() + ) + + PushScreen( + modifier = Modifier.fillMaxSize(), + onToggleMashUpPush = this::onToggleMashUpPush, + onToggleDanggnPush = this::onToggleDanggnPush, + userPreference = userPreference, + onClickBackButton = { + onBackPressed() + } + ) + } + } + } + + private fun onToggleMashUpPush(isChecked: Boolean) { + viewModel.patchPushNotification(isChecked) + } + + private fun onToggleDanggnPush(isChecked: Boolean) { + viewModel.patchDanggnPushNotification(isChecked) + } + + companion object { + fun newIntent(context: Context) = Intent(context, PushActivity::class.java).apply { + putExtra(EXTRA_ANIMATION, NavigationAnimationType.PULL) + } + } + + override val layoutId = R.layout.activity_setting +} diff --git a/app/src/main/java/com/mashup/ui/setting/SettingActivity.kt b/app/src/main/java/com/mashup/ui/setting/SettingActivity.kt index dafdefd8..84ddbadc 100644 --- a/app/src/main/java/com/mashup/ui/setting/SettingActivity.kt +++ b/app/src/main/java/com/mashup/ui/setting/SettingActivity.kt @@ -25,7 +25,7 @@ import com.mashup.core.common.widget.CommonDialog import com.mashup.core.model.data.local.UserPreference import com.mashup.core.ui.theme.MashUpTheme import com.mashup.databinding.ActivitySettingBinding -import com.mashup.feature.SettingScreen +import com.mashup.feature.setting.SettingScreen import com.mashup.ui.login.LoginActivity import com.mashup.ui.withdrawl.WithdrawalActivity import com.mashup.util.AnalyticsManager @@ -42,20 +42,13 @@ class SettingActivity : BaseActivity() { viewBinding.settingScreen.setContent { MashUpTheme { - val userPreference by viewModel.userPreference.collectAsState( - initial = UserPreference.getDefaultInstance() - ) - SettingScreen( modifier = Modifier.fillMaxSize(), onLogout = this::onClickLogoutButton, onDeleteUser = this::moveToDeleteAccount, - onToggleFcm = this::onToggleFcm, onClickSNS = this::onClickSNS, - userPreference = userPreference, - onClickBackButton = { - onBackPressed() - } + onClickPush = this::moveToPushActivity, + onClickBackButton = this::onBackPressed ) } } @@ -96,6 +89,14 @@ class SettingActivity : BaseActivity() { ) } + private fun moveToPushActivity() { + startActivity( + PushActivity.newIntent( + context = this@SettingActivity + ) + ) + } + private fun moveToDeleteAccount() { AnalyticsManager.addEvent(LOG_DELETE_USER) startActivity( @@ -117,13 +118,9 @@ class SettingActivity : BaseActivity() { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link))) } - private fun onToggleFcm(isChecked: Boolean) { - viewModel.patchPushNotification(isChecked) - } - companion object { fun newIntent(context: Context) = Intent(context, SettingActivity::class.java).apply { - putExtra(EXTRA_ANIMATION, NavigationAnimationType.PULL) + putExtra(EXTRA_ANIMATION, NavigationAnimationType.SLIDE) } } diff --git a/app/src/main/java/com/mashup/ui/setting/SettingViewModel.kt b/app/src/main/java/com/mashup/ui/setting/SettingViewModel.kt index 4423936a..6b49c3b4 100644 --- a/app/src/main/java/com/mashup/ui/setting/SettingViewModel.kt +++ b/app/src/main/java/com/mashup/ui/setting/SettingViewModel.kt @@ -1,11 +1,15 @@ package com.mashup.ui.setting -import com.mashup.base.BaseViewModel +import androidx.lifecycle.viewModelScope +import com.mashup.core.common.base.BaseViewModel +import com.mashup.core.model.data.local.UserPreference import com.mashup.data.repository.MemberRepository import com.mashup.datastore.data.repository.UserPreferenceRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn import javax.inject.Inject @HiltViewModel @@ -13,7 +17,11 @@ class SettingViewModel @Inject constructor( private val userPreferenceRepository: UserPreferenceRepository, private val memberRepository: MemberRepository ) : BaseViewModel() { - val userPreference = userPreferenceRepository.getUserPreference() + val userPreference = userPreferenceRepository.getUserPreference().stateIn( + viewModelScope, + SharingStarted.WhileSubscribed(5_000), + UserPreference.getDefaultInstance() + ) private val _onSuccessLogout = MutableSharedFlow() val onSuccessLogout: SharedFlow = _onSuccessLogout @@ -23,10 +31,35 @@ class SettingViewModel @Inject constructor( _onSuccessLogout.emit(Unit) } - fun patchPushNotification(pushNotificationAgreed: Boolean) = mashUpScope { - val result = memberRepository.patchPushNotification(pushNotificationAgreed) + fun patchPushNotification( + pushNotificationAgreed: Boolean + ) = mashUpScope { + val danggnPushAgreed = userPreference.value.danggnPushNotificationAgreed + val result = memberRepository.patchPushNotification( + pushNotificationAgreed = pushNotificationAgreed, + danggnPushNotificationAgreed = danggnPushAgreed + ) if (result.isSuccess()) { - userPreferenceRepository.updateUserPushNotificationAgreed(pushNotificationAgreed) + userPreferenceRepository.updateUserPushNotificationAgreed( + pushNotificationAgreed = pushNotificationAgreed, + danggnPushNotificationAgreed = danggnPushAgreed + ) + } + } + + fun patchDanggnPushNotification( + danggnPushNotificationAgreed: Boolean + ) = mashUpScope { + val pushNotificationAgreed = userPreference.value.pushNotificationAgreed + val result = memberRepository.patchPushNotification( + pushNotificationAgreed = pushNotificationAgreed, + danggnPushNotificationAgreed = danggnPushNotificationAgreed + ) + if (result.isSuccess()) { + userPreferenceRepository.updateUserPushNotificationAgreed( + pushNotificationAgreed = pushNotificationAgreed, + danggnPushNotificationAgreed = danggnPushNotificationAgreed + ) } } diff --git a/app/src/main/java/com/mashup/ui/signup/SignUpViewModel.kt b/app/src/main/java/com/mashup/ui/signup/SignUpViewModel.kt index 4951dbfa..5dea1df6 100644 --- a/app/src/main/java/com/mashup/ui/signup/SignUpViewModel.kt +++ b/app/src/main/java/com/mashup/ui/signup/SignUpViewModel.kt @@ -1,6 +1,6 @@ package com.mashup.ui.signup -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.common.model.Validation import com.mashup.core.firebase.FirebaseRepository import com.mashup.core.model.Platform @@ -8,6 +8,7 @@ import com.mashup.data.repository.MemberRepository import com.mashup.datastore.data.repository.UserPreferenceRepository import com.mashup.ui.signup.state.CodeState import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow @@ -15,7 +16,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.map -import javax.inject.Inject @HiltViewModel class SignUpViewModel @Inject constructor( @@ -81,6 +81,7 @@ class SignUpViewModel @Inject constructor( response.data?.run { userPreferenceRepository.updateUserPreference( + id = memberId, token = token, name = name, platform = Platform.getPlatform(platform), diff --git a/app/src/main/java/com/mashup/ui/signup/fragment/SignUpCodeFragment.kt b/app/src/main/java/com/mashup/ui/signup/fragment/SignUpCodeFragment.kt index 806cdd78..67d186fe 100644 --- a/app/src/main/java/com/mashup/ui/signup/fragment/SignUpCodeFragment.kt +++ b/app/src/main/java/com/mashup/ui/signup/fragment/SignUpCodeFragment.kt @@ -13,8 +13,8 @@ import com.mashup.core.common.model.Validation import com.mashup.core.common.utils.keyboard.TranslateDeferringInsetsAnimationCallback import com.mashup.databinding.FragmentSignUpCodeBinding import com.mashup.network.errorcode.ATTENDANCE_CODE_DUPLICATED -import com.mashup.network.errorcode.INVALID_PLATFORM_NAME -import com.mashup.network.errorcode.MEMBER_INVALID_INVITE +import com.mashup.core.common.constant.INVALID_PLATFORM_NAME +import com.mashup.core.common.constant.MEMBER_INVALID_INVITE import com.mashup.ui.login.LoginType import com.mashup.ui.main.MainActivity import com.mashup.ui.signup.SignUpState diff --git a/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthFragment.kt b/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthFragment.kt index c27a17e1..d7136aa9 100644 --- a/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthFragment.kt +++ b/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthFragment.kt @@ -14,7 +14,7 @@ import com.mashup.core.common.extensions.setFailedUiOfTextField import com.mashup.core.common.extensions.setSuccessUiOfTextField import com.mashup.core.common.utils.keyboard.TranslateDeferringInsetsAnimationCallback import com.mashup.databinding.FragmentSignUpAuthBinding -import com.mashup.network.errorcode.MEMBER_DUPLICATED_IDENTIFICATION +import com.mashup.core.common.constant.MEMBER_DUPLICATED_IDENTIFICATION import com.mashup.ui.signup.SignUpViewModel import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest diff --git a/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthViewModel.kt b/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthViewModel.kt index 3c55351c..c7430eac 100644 --- a/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthViewModel.kt +++ b/app/src/main/java/com/mashup/ui/signup/fragment/auth/SignUpAuthViewModel.kt @@ -1,11 +1,11 @@ package com.mashup.ui.signup.fragment.auth import androidx.lifecycle.viewModelScope -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.common.model.Validation import com.mashup.data.repository.MemberRepository -import com.mashup.network.errorcode.INVALID_MEMBER_ID -import com.mashup.network.errorcode.MEMBER_DUPLICATED_IDENTIFICATION +import com.mashup.core.common.constant.INVALID_MEMBER_ID +import com.mashup.core.common.constant.MEMBER_DUPLICATED_IDENTIFICATION import com.mashup.ui.signup.validationId import com.mashup.ui.signup.validationPwd import com.mashup.ui.signup.validationPwdCheck diff --git a/app/src/main/java/com/mashup/ui/splash/SplashActivity.kt b/app/src/main/java/com/mashup/ui/splash/SplashActivity.kt index b2b84033..12a0ffdf 100644 --- a/app/src/main/java/com/mashup/ui/splash/SplashActivity.kt +++ b/app/src/main/java/com/mashup/ui/splash/SplashActivity.kt @@ -5,17 +5,25 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.activity.viewModels +import androidx.core.app.TaskStackBuilder import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.mashup.R import com.mashup.base.BaseActivity +import com.mashup.constant.EXTRA_LINK import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.common.extensions.setStatusBarDarkTextColor +import com.mashup.core.common.model.ActivityEnterType import com.mashup.core.common.widget.CommonDialog import com.mashup.databinding.ActivitySplashBinding import com.mashup.datastore.data.repository.UserPreferenceRepository -import com.mashup.ui.login.LoginActivity +import com.mashup.service.PushLinkType +import com.mashup.ui.danggn.ShakeDanggnActivity +import com.mashup.ui.login.LoginType +import com.mashup.ui.main.MainActivity +import com.mashup.ui.main.model.MainTab +import com.mashup.ui.qrscan.QRScanActivity import com.mashup.util.AnalyticsManager import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest @@ -77,7 +85,34 @@ class SplashActivity : BaseActivity() { } private fun moveNextScreen() { - startActivity(LoginActivity.newIntent(this@SplashActivity)) + val deepLink = intent.getStringExtra(EXTRA_LINK) ?: "" + val baseIntent = MainActivity.newIntent( + context = this@SplashActivity, + loginType = LoginType.AUTO, + mainTab = if (deepLink == PushLinkType.MYPAGE.name) MainTab.MY_PAGE else MainTab.EVENT + ) + val taskStackBuilder = when (PushLinkType.getPushLinkType(deepLink)) { + PushLinkType.DANGGN -> { + TaskStackBuilder.create(this) + .addNextIntentWithParentStack(baseIntent) + .addNextIntent( + ShakeDanggnActivity.newIntent( + context = this, + type = ActivityEnterType.ALARM + ) + ) + } + PushLinkType.QR -> { + TaskStackBuilder.create(this) + .addNextIntentWithParentStack(baseIntent) + .addNextIntent(QRScanActivity.newIntent(this)) + } + else -> { + TaskStackBuilder.create(this) + .addNextIntentWithParentStack(baseIntent) + } + } + taskStackBuilder.startActivities() finish() } diff --git a/app/src/main/java/com/mashup/ui/splash/SplashViewModel.kt b/app/src/main/java/com/mashup/ui/splash/SplashViewModel.kt index 20a4fff9..4b5df6a7 100644 --- a/app/src/main/java/com/mashup/ui/splash/SplashViewModel.kt +++ b/app/src/main/java/com/mashup/ui/splash/SplashViewModel.kt @@ -2,7 +2,7 @@ package com.mashup.ui.splash import android.content.Context import androidx.core.content.pm.PackageInfoCompat -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.firebase.FirebaseRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/mashup/ui/webview/WebViewViewModel.kt b/app/src/main/java/com/mashup/ui/webview/WebViewViewModel.kt index 8525a59a..1ef8db98 100644 --- a/app/src/main/java/com/mashup/ui/webview/WebViewViewModel.kt +++ b/app/src/main/java/com/mashup/ui/webview/WebViewViewModel.kt @@ -2,7 +2,7 @@ package com.mashup.ui.webview import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.constant.EXTRA_TITLE_KEY import com.mashup.constant.EXTRA_URL_KEY import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/app/src/main/java/com/mashup/ui/withdrawl/WithdrawalViewModel.kt b/app/src/main/java/com/mashup/ui/withdrawl/WithdrawalViewModel.kt index 9479dc46..348f2d70 100644 --- a/app/src/main/java/com/mashup/ui/withdrawl/WithdrawalViewModel.kt +++ b/app/src/main/java/com/mashup/ui/withdrawl/WithdrawalViewModel.kt @@ -1,6 +1,6 @@ package com.mashup.ui.withdrawl -import com.mashup.base.BaseViewModel +import com.mashup.core.common.base.BaseViewModel import com.mashup.core.common.model.Validation import com.mashup.data.repository.MemberRepository import com.mashup.datastore.data.repository.UserPreferenceRepository diff --git a/app/src/main/res/layout/activity_danggn_info.xml b/app/src/main/res/layout/activity_danggn_info.xml new file mode 100644 index 00000000..dce25d6c --- /dev/null +++ b/app/src/main/res/layout/activity_danggn_info.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_shake_danggn.xml b/app/src/main/res/layout/activity_shake_danggn.xml new file mode 100644 index 00000000..3b98942f --- /dev/null +++ b/app/src/main/res/layout/activity_shake_danggn.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_schedule.xml b/app/src/main/res/layout/fragment_schedule.xml index b441a791..4f91a58e 100644 --- a/app/src/main/res/layout/fragment_schedule.xml +++ b/app/src/main/res/layout/fragment_schedule.xml @@ -26,6 +26,16 @@ app:layout_constraintEnd_toEndOf="parent" tools:text="@string/event_list_title" /> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v27/themes.xml b/app/src/main/res/values-v27/themes.xml new file mode 100644 index 00000000..04e678cf --- /dev/null +++ b/app/src/main/res/values-v27/themes.xml @@ -0,0 +1,29 @@ + + + + + + + + + + \ 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 4514cbc2..04e678cf 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -8,6 +8,8 @@ true @style/AppBottomSheetDialogTheme + + true