From a5284e4f763f03c475e00d7c676d0c0557c94b8b Mon Sep 17 00:00:00 2001 From: blueme0 Date: Mon, 12 Feb 2024 10:56:37 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[feat/#133]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 + .../presentation/home/HomeFragment.kt | 8 +- .../notification/AlertsListActivity.kt | 78 ++++++++++++++++++ .../notification/AlertsListAdapter.kt | 80 +++++++++++++++++++ .../main/res/layout/activity_alerts_list.xml | 75 +++++++++++++++++ app/src/main/res/layout/item_alerts_list.xml | 55 +++++++++++++ app/src/main/res/values/strings.xml | 3 + .../com/teumteum/domain/entity/TeumAlert.kt | 12 +++ 8 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt create mode 100644 app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListAdapter.kt create mode 100644 app/src/main/res/layout/activity_alerts_list.xml create mode 100644 app/src/main/res/layout/item_alerts_list.xml create mode 100644 core/domain/src/main/java/com/teumteum/domain/entity/TeumAlert.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5d22693..59290604 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -108,6 +108,9 @@ + )?.openActivitySlideAnimation() + } + } ) ) } diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt new file mode 100644 index 00000000..3c6a8e1e --- /dev/null +++ b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt @@ -0,0 +1,78 @@ +package com.teumteum.teumteum.presentation.notification + +import android.os.Bundle +import com.teumteum.base.BindingActivity +import com.teumteum.base.component.appbar.AppBarLayout +import com.teumteum.base.component.appbar.AppBarMenu +import com.teumteum.base.databinding.LayoutCommonAppbarBinding +import com.teumteum.domain.entity.TeumAlert +import com.teumteum.teumteum.R +import com.teumteum.teumteum.databinding.ActivityAlertsListBinding + +class AlertsListActivity + : BindingActivity(R.layout.activity_alerts_list), AppBarLayout { + + private lateinit var adapter: AlertsListAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + initAppBarLayout() + initList() + } + + override val appBarBinding: LayoutCommonAppbarBinding + get() = binding.appBar + + override fun initAppBarLayout() { + setAppBarHeight(48) + + addMenuToLeft( + AppBarMenu.IconStyle( + resourceId = R.drawable.ic_arrow_left_l, + useRippleEffect = false, + clickEvent = ::finish + ) + ) + setAppBarTitleText(R.string.alerts_list_title) + } + + private fun initItems() { + adapter.setItems(listOf( + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-01-30T16:33:00", false), + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-01-31T16:33:00", false), + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-02-10T16:33:00", false), + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-02-11T16:33:00", false), + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-02-12T09:33:00", false), + TeumAlert("틈 채우기", "한별님이 당신을 추천했어요!", RECOMMEND_USER, "2024-02-12T10:33:00", false) + )) + } + + private fun initList() { + adapter = AlertsListAdapter { + when (it.type) { + // 알림 리스트에서 클릭 시 이동하는 정책이 있다면 + BEFORE_MEETING -> { + // 틈틈으로 이동 + // openActivitySlideAnimation() + } + END_MEETING -> { + // 해당 모임 종료 화면으로 이동 + // openActivitySlideAnimation() + } + RECOMMEND_USER -> { + // 마이페이지로 이동 + // openActivitySlideAnimation() + } + } + } + initItems() + binding.rvAlertsList.adapter = adapter + } + + companion object { + private const val BEFORE_MEETING = "BEFORE_MEETING" + private const val END_MEETING = "END_MEETING" + private const val RECOMMEND_USER = "RECOMMEND_USER" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListAdapter.kt b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListAdapter.kt new file mode 100644 index 00000000..018876cb --- /dev/null +++ b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListAdapter.kt @@ -0,0 +1,80 @@ +package com.teumteum.teumteum.presentation.notification + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.teumteum.base.R.* +import com.teumteum.base.util.extension.setOnSingleClickListener +import com.teumteum.domain.entity.TeumAlert +import com.teumteum.teumteum.databinding.ItemAlertsListBinding +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +class AlertsListAdapter(private val itemClick: (TeumAlert) -> (Unit)) : + RecyclerView.Adapter() { + private val alertList = mutableListOf() + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): AlertsListViewHolder { + val binding = ItemAlertsListBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + return AlertsListViewHolder(binding, parent.context, itemClick) + } + + override fun onBindViewHolder(holder: AlertsListViewHolder, position: Int) { + holder.onBind(alertList[position]) + } + + override fun getItemCount(): Int = alertList.size + + fun setItems(newItems: List) { + alertList.clear() + alertList.addAll(newItems.sortedByDescending { + LocalDateTime.parse(it.createdAt, DateTimeFormatter.ISO_LOCAL_DATE_TIME) + }) + notifyDataSetChanged() + } + + class AlertsListViewHolder( + private val binding: ItemAlertsListBinding, + private val context: Context, + private val itemClick: (TeumAlert) -> (Unit) + ) : RecyclerView.ViewHolder(binding.root) { + + fun onBind(item: TeumAlert) { + binding.tvTitle.text = item.title + binding.tvContent.text = item.body + binding.tvTime.text = getTimeDifference(item.createdAt) + + if (!item.isRead) { + binding.root.setBackgroundColor(context.getColor(color.elevation_level01)) + } else { + binding.root.setBackgroundColor(context.getColor(color.transparent)) + } + binding.root.setOnSingleClickListener { + itemClick(item) + } + } + + private fun getTimeDifference(inputDateTime: String): String { + val currentTime = LocalDateTime.now() + val formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME + val inputTime = LocalDateTime.parse(inputDateTime, formatter) + + val diffInMinutes = java.time.Duration.between(inputTime, currentTime).toMinutes() + val diffInHours = java.time.Duration.between(inputTime, currentTime).toHours() + + return when { + diffInMinutes < 60 -> "${diffInMinutes}분 전" + diffInHours < 24 -> "${diffInHours}시간 전" + else -> "${inputTime.monthValue}월 ${inputTime.dayOfMonth}일" + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_alerts_list.xml b/app/src/main/res/layout/activity_alerts_list.xml new file mode 100644 index 00000000..759e9a94 --- /dev/null +++ b/app/src/main/res/layout/activity_alerts_list.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alerts_list.xml b/app/src/main/res/layout/item_alerts_list.xml new file mode 100644 index 00000000..5f1ffb40 --- /dev/null +++ b/app/src/main/res/layout/item_alerts_list.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + \ 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 da7142de..db0550c9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -338,5 +338,8 @@ 서로의 관심사 틈을 채우기 teum_notification_channel + 알림 + 알림이 아직 없어요 + 최대 한 달 전까지의 알림을 확인할 수 있어요 \ No newline at end of file diff --git a/core/domain/src/main/java/com/teumteum/domain/entity/TeumAlert.kt b/core/domain/src/main/java/com/teumteum/domain/entity/TeumAlert.kt new file mode 100644 index 00000000..18ad702c --- /dev/null +++ b/core/domain/src/main/java/com/teumteum/domain/entity/TeumAlert.kt @@ -0,0 +1,12 @@ +package com.teumteum.domain.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class TeumAlert ( + val title: String, + val body: String, + val type: String, + val createdAt: String, + val isRead: Boolean +) \ No newline at end of file From 7a4d63c09a082e6c65c89a9eea2ae333946e2853 Mon Sep 17 00:00:00 2001 From: blueme0 Date: Mon, 12 Feb 2024 11:39:57 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[feat/#133]=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20-=20=ED=91=B8=EC=8B=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20on/off=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teumteum/config/TeumMessagingService.kt | 20 ++++++++++--------- .../setting/viewModel/SettingViewModel.kt | 5 +++-- .../data/local/TeumTeumDataStoreImpl.kt | 5 +++++ .../data/repository/SettingRepositoryImpl.kt | 8 +++++++- .../com/teumteum/domain/TeumTeumDataStore.kt | 1 + .../domain/repository/SettingRepository.kt | 2 ++ 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt b/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt index 8eb945c1..64ad7b3a 100644 --- a/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt +++ b/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt @@ -52,15 +52,17 @@ class TeumMessagingService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) { super.onMessageReceived(message) - if (dataStore.isLogin) { - if (message.data.isNotEmpty() && message.data["title"].toString() != EMPTY) { - sendNotificationAlarm( - Message(message.data["title"].toString(), message.data["content"].toString()) - ) - } - else { - message.notification?.let { - sendNotificationAlarm(Message(it.title.toString(), it.body.toString())) + if (dataStore.onNotification) { + if (dataStore.isLogin) { + if (message.data.isNotEmpty() && message.data["title"].toString() != EMPTY) { + sendNotificationAlarm( + Message(message.data["title"].toString(), message.data["content"].toString()) + ) + } + else { + message.notification?.let { + sendNotificationAlarm(Message(it.title.toString(), it.body.toString())) + } } } } diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/mypage/setting/viewModel/SettingViewModel.kt b/app/src/main/java/com/teumteum/teumteum/presentation/mypage/setting/viewModel/SettingViewModel.kt index 19881687..51278d8a 100644 --- a/app/src/main/java/com/teumteum/teumteum/presentation/mypage/setting/viewModel/SettingViewModel.kt +++ b/app/src/main/java/com/teumteum/teumteum/presentation/mypage/setting/viewModel/SettingViewModel.kt @@ -142,11 +142,12 @@ class SettingViewModel @Inject constructor( return false } - private val _alarmState = MutableStateFlow(false) + private val _alarmState = MutableStateFlow(settingRepository.getNotification()) val alarmState: StateFlow = _alarmState.asStateFlow() fun onToggleChange(newToggleState: Boolean) { - _alarmState.value = newToggleState + settingRepository.setNotification(newToggleState) + _alarmState.value = settingRepository.getNotification() } private val _settingStatus = MutableStateFlow(SettingStatus.DEFAULT) diff --git a/core/data/src/main/java/com/teumteum/data/local/TeumTeumDataStoreImpl.kt b/core/data/src/main/java/com/teumteum/data/local/TeumTeumDataStoreImpl.kt index 3d9f5e1d..98d79a96 100644 --- a/core/data/src/main/java/com/teumteum/data/local/TeumTeumDataStoreImpl.kt +++ b/core/data/src/main/java/com/teumteum/data/local/TeumTeumDataStoreImpl.kt @@ -37,6 +37,10 @@ class TeumTeumDataStoreImpl @Inject constructor( get() = userPref.getBoolean(PREF_ASKED_NOTIFICATION, false) set(value) = userPref.edit { putBoolean(PREF_ASKED_NOTIFICATION, value)} + override var onNotification: Boolean + get() = userPref.getBoolean(PREF_ON_NOTIFICATION, true) + set(value) = userPref.edit { putBoolean(PREF_ON_NOTIFICATION, value)} + override fun clearLocalPref() = userPref.edit { clear() } companion object { @@ -47,5 +51,6 @@ class TeumTeumDataStoreImpl @Inject constructor( private const val PREF_IS_FIRST_AFTER_INSTALL = "IS_FIRST_AFTER_INSTALL" private const val PREF_DEVICE_TOKEN = "DEVICE_TOKEN" private const val PREF_ASKED_NOTIFICATION = "ASKED_NOTIFICATION" + private const val PREF_ON_NOTIFICATION = "ON_NOTIFICATION" } } diff --git a/core/data/src/main/java/com/teumteum/data/repository/SettingRepositoryImpl.kt b/core/data/src/main/java/com/teumteum/data/repository/SettingRepositoryImpl.kt index a4cc5d8c..e1395815 100644 --- a/core/data/src/main/java/com/teumteum/data/repository/SettingRepositoryImpl.kt +++ b/core/data/src/main/java/com/teumteum/data/repository/SettingRepositoryImpl.kt @@ -9,7 +9,8 @@ import com.teumteum.domain.repository.SettingRepository import javax.inject.Inject class SettingRepositoryImpl @Inject constructor( - private val dataSource: RemoteSettingDataSource + private val dataSource: RemoteSettingDataSource, + private val dataStore: TeumTeumDataStore ): SettingRepository { override suspend fun logOut(): Result { return runCatching { @@ -47,5 +48,10 @@ class SettingRepositoryImpl @Inject constructor( } } + override fun setNotification(isActivated: Boolean) { + dataStore.onNotification = isActivated + } + + override fun getNotification(): Boolean = dataStore.onNotification } \ No newline at end of file diff --git a/core/domain/src/main/java/com/teumteum/domain/TeumTeumDataStore.kt b/core/domain/src/main/java/com/teumteum/domain/TeumTeumDataStore.kt index 7953fc9a..7aba189b 100644 --- a/core/domain/src/main/java/com/teumteum/domain/TeumTeumDataStore.kt +++ b/core/domain/src/main/java/com/teumteum/domain/TeumTeumDataStore.kt @@ -9,6 +9,7 @@ interface TeumTeumDataStore { var userInfo: String var deviceToken: String var askedNotification: Boolean + var onNotification: Boolean fun clearLocalPref() } diff --git a/core/domain/src/main/java/com/teumteum/domain/repository/SettingRepository.kt b/core/domain/src/main/java/com/teumteum/domain/repository/SettingRepository.kt index 0c979cf2..1bdd98cb 100644 --- a/core/domain/src/main/java/com/teumteum/domain/repository/SettingRepository.kt +++ b/core/domain/src/main/java/com/teumteum/domain/repository/SettingRepository.kt @@ -8,4 +8,6 @@ interface SettingRepository { suspend fun signOut(withDrawReasons: WithDrawReasons): Result suspend fun getMyPageOpenMeeting(participantUserId: Long): Result> suspend fun getMyPageClosedMeeting(participantUserId: Long): Result> + fun setNotification(isActivated: Boolean) + fun getNotification(): Boolean } \ No newline at end of file From 3176f4443c15c6a9a0d1d710635d99a6723e8186 Mon Sep 17 00:00:00 2001 From: blueme0 Date: Mon, 12 Feb 2024 14:05:27 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[feat/#133]=20=EC=95=8C=EB=A6=BC=20type=20?= =?UTF-8?q?=EB=B3=84=EB=A1=9C=20=ED=99=94=EB=A9=B4=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teumteum/config/TeumMessagingService.kt | 23 +++++++++-------- .../teumteum/presentation/MainActivity.kt | 25 +++++++++++++++++-- .../presentation/splash/SplashActivity.kt | 15 ++++++++++- .../com/teumteum/domain/entity/Message.kt | 9 +++++++ 4 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 core/domain/src/main/java/com/teumteum/domain/entity/Message.kt diff --git a/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt b/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt index 64ad7b3a..06e28073 100644 --- a/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt +++ b/app/src/main/java/com/teumteum/teumteum/config/TeumMessagingService.kt @@ -11,6 +11,7 @@ import com.google.firebase.messaging.RemoteMessage import com.teumteum.data.model.request.toDeviceToken import com.teumteum.data.service.UserService import com.teumteum.domain.TeumTeumDataStore +import com.teumteum.domain.entity.Message import com.teumteum.teumteum.R import com.teumteum.teumteum.presentation.splash.SplashActivity import dagger.hilt.android.AndroidEntryPoint @@ -54,16 +55,17 @@ class TeumMessagingService : FirebaseMessagingService() { if (dataStore.onNotification) { if (dataStore.isLogin) { - if (message.data.isNotEmpty() && message.data["title"].toString() != EMPTY) { - sendNotificationAlarm( - Message(message.data["title"].toString(), message.data["content"].toString()) - ) + val alertMessage = Message("", "", "") + if (message.data.isNotEmpty()) { + alertMessage.title = message.notification?.title.toString() + alertMessage.body = message.notification?.body.toString() + alertMessage.type = message.data["type"].toString() } - else { - message.notification?.let { - sendNotificationAlarm(Message(it.title.toString(), it.body.toString())) - } + if (alertMessage.type == END_MEETING) { + alertMessage.meetingId = message.data["meetingId"]?.toInt() + alertMessage.participants = message.data["participants"]?.toList()?.map { it.digitToInt() } } + if (alertMessage.title.isNotEmpty()) sendNotificationAlarm(alertMessage) } } } @@ -72,6 +74,8 @@ class TeumMessagingService : FirebaseMessagingService() { val requestCode = (System.currentTimeMillis() % 10000).toInt() val intent = Intent(this, SplashActivity::class.java) intent.putExtra("isFromAlarm", true) + intent.putExtra("message", message) + Timber.tag("teum-alerts").d("message: ${message.title}, ${message.type}, ${message.body}, ${message.meetingId}, ${message.participants.toString()}") intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity( @@ -96,7 +100,6 @@ class TeumMessagingService : FirebaseMessagingService() { companion object { const val EMPTY = "null" + private const val END_MEETING = "END_MEETING" } - - private data class Message(var title: String, var body: String) } \ No newline at end of file diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/MainActivity.kt b/app/src/main/java/com/teumteum/teumteum/presentation/MainActivity.kt index d05ff5d5..99a433cb 100644 --- a/app/src/main/java/com/teumteum/teumteum/presentation/MainActivity.kt +++ b/app/src/main/java/com/teumteum/teumteum/presentation/MainActivity.kt @@ -15,6 +15,7 @@ import androidx.navigation.ui.setupWithNavController import com.teumteum.base.BindingActivity import com.teumteum.base.util.extension.boolExtra import com.teumteum.base.util.extension.intExtra +import com.teumteum.domain.entity.Message import com.teumteum.teumteum.R import com.teumteum.teumteum.databinding.ActivityMainBinding import com.teumteum.teumteum.presentation.home.HomeFragmentDirections @@ -44,7 +45,20 @@ class MainActivity : BindingActivity(R.layout.activity_main if (isFromAlarm) { - val action = HomeFragmentDirections.actionHomeFragmentToFragmentFamiliar() + val message = intent.getSerializableExtra(MESSAGE) as Message + var action = HomeFragmentDirections.actionHomeFragmentToFragmentFamiliar() + when (message.type) { + BEFORE_MEETING -> { + } + END_MEETING -> { +// val meetingId = message.meetingId +// val participants = message.participants +// action = HomeFragmentDirections.{홈 -> 유저리뷰로 이동하는 navi} + } + RECOMMEND_USER -> { + action = HomeFragmentDirections.actionHomeFragmentToFragmentMyPage() + } + } val navHostFragment = supportFragmentManager.findFragmentById(R.id.fl_main) as NavHostFragment navHostFragment.navController.navigate(action) } @@ -138,7 +152,14 @@ class MainActivity : BindingActivity(R.layout.activity_main } fun getIntent(context: Context, id: Int, isFromAlarm: Boolean = false) = Intent(context, MainActivity::class.java).apply { putExtra("id", id) - putExtra("isFromAlarm", isFromAlarm) + putExtra(IS_FROM_ALARM, isFromAlarm) } + + private const val IS_FROM_ALARM = "isFromAlarm" + private const val MESSAGE = "message" + + private const val BEFORE_MEETING = "BEFORE_MEETING" + private const val END_MEETING = "END_MEETING" + private const val RECOMMEND_USER = "RECOMMEND_USER" } } diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt b/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt index 681d39ed..db620d33 100644 --- a/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt +++ b/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt @@ -1,6 +1,7 @@ package com.teumteum.teumteum.presentation.splash import android.content.Intent +import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper @@ -9,6 +10,7 @@ import androidx.appcompat.app.AlertDialog import androidx.lifecycle.lifecycleScope import com.teumteum.base.BindingActivity import com.teumteum.base.util.extension.defaultSnackBar +import com.teumteum.domain.entity.Message import com.teumteum.teumteum.R import com.teumteum.teumteum.databinding.ActivitySplashBinding import com.teumteum.teumteum.presentation.MainActivity @@ -25,15 +27,23 @@ class SplashActivity private val viewModel by viewModels() private var isFromAlarm = false + private var message = Message("", "", "") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isFromAlarm = intent.getBooleanExtra(IS_FROM_ALARM, false) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) getMessage() checkNetwork() setUpObserver() } + private fun getMessage() { + if (isFromAlarm) { + message = intent.getSerializableExtra(MESSAGE) as Message + } + } + private fun setUpObserver() { viewModel.myInfo.observe(this) { AuthUtils.setMyInfo(context = this, myInfo = it) @@ -108,7 +118,9 @@ class SplashActivity } private fun startHomeScreen() { - startActivity(MainActivity.getIntent(this, -1, isFromAlarm = isFromAlarm)) + val intent = MainActivity.getIntent(this, -1, isFromAlarm = isFromAlarm) + if (isFromAlarm) intent.putExtra(MESSAGE, message) + startActivity(intent) finish() } @@ -118,5 +130,6 @@ class SplashActivity const val HAVE_TO_SIGN_IN = 2 const val IS_FROM_ALARM = "isFromAlarm" + const val MESSAGE = "message" } } \ No newline at end of file diff --git a/core/domain/src/main/java/com/teumteum/domain/entity/Message.kt b/core/domain/src/main/java/com/teumteum/domain/entity/Message.kt new file mode 100644 index 00000000..a11f403d --- /dev/null +++ b/core/domain/src/main/java/com/teumteum/domain/entity/Message.kt @@ -0,0 +1,9 @@ +package com.teumteum.domain.entity + +data class Message( + var title: String, + var body: String, + var type: String, + var meetingId: Int? = -1, + var participants: List? = listOf() +): java.io.Serializable \ No newline at end of file From be6876df2df6c5ca2c4969664eed2c12a18c5bf0 Mon Sep 17 00:00:00 2001 From: blueme0 Date: Mon, 12 Feb 2024 15:05:20 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[feat/#133]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=84=9C=EB=B2=84=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/AlertsListActivity.kt | 32 ++++++++++++++- .../notification/AlertsViewModel.kt | 40 +++++++++++++++++++ .../datasource/remote/RemoteUserDataSource.kt | 5 +++ .../data/repository/UserRepositoryImpl.kt | 6 +++ .../com/teumteum/data/service/UserService.kt | 4 ++ .../java/com/teumteum/domain/entity/Alerts.kt | 8 ++++ .../domain/repository/UserRepository.kt | 4 +- 7 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsViewModel.kt create mode 100644 core/domain/src/main/java/com/teumteum/domain/entity/Alerts.kt diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt index 3c6a8e1e..54177ac5 100644 --- a/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt +++ b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsListActivity.kt @@ -1,24 +1,37 @@ package com.teumteum.teumteum.presentation.notification import android.os.Bundle +import androidx.activity.viewModels +import androidx.core.view.isVisible +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope import com.teumteum.base.BindingActivity import com.teumteum.base.component.appbar.AppBarLayout import com.teumteum.base.component.appbar.AppBarMenu import com.teumteum.base.databinding.LayoutCommonAppbarBinding +import com.teumteum.base.util.extension.defaultToast import com.teumteum.domain.entity.TeumAlert import com.teumteum.teumteum.R import com.teumteum.teumteum.databinding.ActivityAlertsListBinding +import com.teumteum.teumteum.presentation.group.GroupListUiState +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +@AndroidEntryPoint class AlertsListActivity : BindingActivity(R.layout.activity_alerts_list), AppBarLayout { private lateinit var adapter: AlertsListAdapter + private val viewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initAppBarLayout() initList() + viewModel.getAlerts() + observe() } override val appBarBinding: LayoutCommonAppbarBinding @@ -48,6 +61,24 @@ class AlertsListActivity )) } + private fun observe() { + viewModel.alertsData.flowWithLifecycle(lifecycle) + .onEach { + binding.clEmpty.isVisible = it is AlertsListUiState.Empty + binding.tvNoticeEmpty.isVisible = it !is AlertsListUiState.Empty + binding.rvAlertsList.isVisible = it !is AlertsListUiState.Empty + when (it) { + is AlertsListUiState.SetAlerts -> { + adapter.setItems(it.data) + } + is AlertsListUiState.Failure -> { + defaultToast(it.msg) + } + else -> {} + } + }.launchIn(lifecycleScope) + } + private fun initList() { adapter = AlertsListAdapter { when (it.type) { @@ -66,7 +97,6 @@ class AlertsListActivity } } } - initItems() binding.rvAlertsList.adapter = adapter } diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsViewModel.kt b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsViewModel.kt new file mode 100644 index 00000000..d5df66e9 --- /dev/null +++ b/app/src/main/java/com/teumteum/teumteum/presentation/notification/AlertsViewModel.kt @@ -0,0 +1,40 @@ +package com.teumteum.teumteum.presentation.notification + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.teumteum.domain.entity.TeumAlert +import com.teumteum.domain.repository.UserRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AlertsViewModel @Inject constructor( + private val repository: UserRepository +) : ViewModel() { + + private val _alertsData = MutableStateFlow(AlertsListUiState.Init) + val alertsData: StateFlow = _alertsData + + fun getAlerts() { + viewModelScope.launch { + repository.getAlerts() + .onSuccess { + if (it.alerts.isEmpty()) _alertsData.value = AlertsListUiState.Empty + else _alertsData.value = AlertsListUiState.SetAlerts(it.alerts) + } + .onFailure { + _alertsData.value = AlertsListUiState.Failure("알림 가져오기 실패") + } + } + } +} + +sealed interface AlertsListUiState { + object Init : AlertsListUiState + object Empty : AlertsListUiState + data class SetAlerts(val data: List) : AlertsListUiState + data class Failure(val msg: String) : AlertsListUiState +} \ No newline at end of file diff --git a/core/data/src/main/java/com/teumteum/data/datasource/remote/RemoteUserDataSource.kt b/core/data/src/main/java/com/teumteum/data/datasource/remote/RemoteUserDataSource.kt index 484ac2d6..da4901a2 100644 --- a/core/data/src/main/java/com/teumteum/data/datasource/remote/RemoteUserDataSource.kt +++ b/core/data/src/main/java/com/teumteum/data/datasource/remote/RemoteUserDataSource.kt @@ -3,6 +3,7 @@ package com.teumteum.data.datasource.remote import com.teumteum.data.model.request.RequestDeviceToken import com.teumteum.data.model.request.RequestUserInfoWithOAuthId import com.teumteum.data.service.UserService +import com.teumteum.domain.entity.Alerts import com.teumteum.domain.entity.Friend import com.teumteum.domain.entity.FriendRecommend import com.teumteum.domain.entity.SignUpResult @@ -59,4 +60,8 @@ class RemoteUserDataSource @Inject constructor( suspend fun patchDeviceToken(token: RequestDeviceToken): Boolean { return service.patchDeviceToken(token).isSuccessful } + + suspend fun getAlerts(): Alerts { + return service.getAlerts() + } } \ No newline at end of file diff --git a/core/data/src/main/java/com/teumteum/data/repository/UserRepositoryImpl.kt b/core/data/src/main/java/com/teumteum/data/repository/UserRepositoryImpl.kt index 11ef331c..ac565ba2 100644 --- a/core/data/src/main/java/com/teumteum/data/repository/UserRepositoryImpl.kt +++ b/core/data/src/main/java/com/teumteum/data/repository/UserRepositoryImpl.kt @@ -5,6 +5,7 @@ import com.google.gson.GsonBuilder import com.teumteum.domain.TeumTeumDataStore import com.teumteum.data.datasource.remote.RemoteUserDataSource import com.teumteum.data.model.request.RequestUserInfo +import com.teumteum.domain.entity.Alerts import com.teumteum.domain.entity.Friend import com.teumteum.domain.entity.FriendMyPage import com.teumteum.domain.entity.FriendRecommend @@ -101,4 +102,9 @@ class UserRepositoryImpl @Inject constructor( } } + override suspend fun getAlerts(): Result { + return runCatching { + dataSource.getAlerts() + } + } } \ No newline at end of file diff --git a/core/data/src/main/java/com/teumteum/data/service/UserService.kt b/core/data/src/main/java/com/teumteum/data/service/UserService.kt index 7264e55d..490dc399 100644 --- a/core/data/src/main/java/com/teumteum/data/service/UserService.kt +++ b/core/data/src/main/java/com/teumteum/data/service/UserService.kt @@ -2,6 +2,7 @@ package com.teumteum.data.service import com.teumteum.data.model.request.RequestDeviceToken import com.teumteum.data.model.request.RequestUserInfoWithOAuthId +import com.teumteum.domain.entity.Alerts import com.teumteum.domain.entity.Friend import com.teumteum.domain.entity.FriendRecommend import com.teumteum.domain.entity.SignUpResult @@ -65,5 +66,8 @@ interface UserService { suspend fun patchDeviceToken( @Body token: RequestDeviceToken ): Response + + @GET("alerts") + suspend fun getAlerts(): Alerts } diff --git a/core/domain/src/main/java/com/teumteum/domain/entity/Alerts.kt b/core/domain/src/main/java/com/teumteum/domain/entity/Alerts.kt new file mode 100644 index 00000000..9e5c33d7 --- /dev/null +++ b/core/domain/src/main/java/com/teumteum/domain/entity/Alerts.kt @@ -0,0 +1,8 @@ +package com.teumteum.domain.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class Alerts( + val alerts: List +) diff --git a/core/domain/src/main/java/com/teumteum/domain/repository/UserRepository.kt b/core/domain/src/main/java/com/teumteum/domain/repository/UserRepository.kt index 5590b65d..0872547e 100644 --- a/core/domain/src/main/java/com/teumteum/domain/repository/UserRepository.kt +++ b/core/domain/src/main/java/com/teumteum/domain/repository/UserRepository.kt @@ -1,5 +1,6 @@ package com.teumteum.domain.repository +import com.teumteum.domain.entity.Alerts import com.teumteum.domain.entity.Friend import com.teumteum.domain.entity.FriendRecommend import com.teumteum.domain.entity.Friends @@ -25,6 +26,5 @@ interface UserRepository { suspend fun updateUserInfo(user: UserInfo): Result suspend fun getFriendInfo(userId: Long): UserInfo? suspend fun postFriend(userId: Long): Result - - + suspend fun getAlerts(): Result } \ No newline at end of file From 0405953a765ff5b8d2ba1afc8de0972458123356 Mon Sep 17 00:00:00 2001 From: blueme0 Date: Tue, 13 Feb 2024 02:48:55 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[fix/#133]=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teumteum/presentation/splash/SplashActivity.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt b/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt index cd3b1fdc..7685b0c2 100644 --- a/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt +++ b/app/src/main/java/com/teumteum/teumteum/presentation/splash/SplashActivity.kt @@ -33,7 +33,6 @@ class SplashActivity isFromAlarm = intent.getBooleanExtra(IS_FROM_ALARM, false) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) getMessage() checkNetwork() - setUpObserver() } private fun getMessage() { @@ -42,13 +41,6 @@ class SplashActivity } } - private fun setUpObserver() { - viewModel.myInfo.observe(this) { - AuthUtils.setMyInfo(context = this, myInfo = it) - Timber.tag("setMyInfo").d("$it") - } - } - private fun checkNetwork() { if (NetworkManager.checkNetworkState(this)) checkAutoLogin() else {