diff --git a/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboard.kt b/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboard.kt index 5d3513be8..f30e96777 100644 --- a/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboard.kt +++ b/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboard.kt @@ -3,33 +3,30 @@ package com.mulberry.ody.data.local.service import android.content.Context import com.mulberry.ody.data.local.db.OdyDatastore import com.mulberry.ody.domain.common.toMilliSeconds -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import java.time.LocalDateTime import javax.inject.Inject -class EtaDashboard @Inject constructor( - val context: Context, - val odyDatastore: OdyDatastore, -) { - fun open( - meetingId: Long, - meetingTime: LocalDateTime, +class EtaDashboard + @Inject + constructor( + val context: Context, + val odyDatastore: OdyDatastore, ) { - if (!isLoggedIn()) { - return + fun open( + meetingId: Long, + meetingTime: LocalDateTime, + ) { + if (!isLoggedIn()) { + return + } + val meetingTimeMills = meetingTime.toMilliSeconds() + val serviceIntent = EtaDashboardService.getIntent(context, meetingId, meetingTimeMills, isOpen = true) + context.startForegroundService(serviceIntent) } - val meetingTimeMills = meetingTime.toMilliSeconds() - val serviceIntent = EtaDashboardService.getIntent(context, meetingId, meetingTimeMills, isOpen = true) - context.startForegroundService(serviceIntent) - } - private fun isLoggedIn(): Boolean { - return runBlocking { odyDatastore.getAuthToken().first().isSuccess } + private fun isLoggedIn(): Boolean { + return runBlocking { odyDatastore.getAuthToken().first().isSuccess } + } } -} diff --git a/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboardService.kt b/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboardService.kt index 5331d9a06..31f00309a 100644 --- a/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboardService.kt +++ b/android/app/src/main/java/com/mulberry/ody/data/local/service/EtaDashboardService.kt @@ -68,7 +68,10 @@ class EtaDashboardService : Service() { return START_REDELIVER_INTENT } - private fun openEtaDashboard(meetingId: Long, meetingTime: Long) { + private fun openEtaDashboard( + meetingId: Long, + meetingTime: Long, + ) { val notification = etaDashboardNotification.createNotification(meetingId) startForeground(meetingId.toInt(), notification) diff --git a/android/app/src/main/java/com/mulberry/ody/domain/model/NotificationType.kt b/android/app/src/main/java/com/mulberry/ody/domain/model/NotificationType.kt index 2cd12f936..c7e853818 100644 --- a/android/app/src/main/java/com/mulberry/ody/domain/model/NotificationType.kt +++ b/android/app/src/main/java/com/mulberry/ody/domain/model/NotificationType.kt @@ -25,10 +25,8 @@ enum class FCMNotificationType : FCMType { DEPARTURE_REMINDER, NUDGE, ETA_NOTICE, - ; } enum class FCMMessageType : FCMType { ETA_SCHEDULING_NOTICE, - ; } diff --git a/android/app/src/main/java/com/mulberry/ody/presentation/join/MeetingJoinViewModel.kt b/android/app/src/main/java/com/mulberry/ody/presentation/join/MeetingJoinViewModel.kt index 7aa65a43a..354f27afe 100644 --- a/android/app/src/main/java/com/mulberry/ody/presentation/join/MeetingJoinViewModel.kt +++ b/android/app/src/main/java/com/mulberry/ody/presentation/join/MeetingJoinViewModel.kt @@ -11,7 +11,6 @@ import com.mulberry.ody.domain.model.Address import com.mulberry.ody.domain.model.MeetingJoinInfo import com.mulberry.ody.domain.repository.location.AddressRepository import com.mulberry.ody.domain.repository.ody.JoinRepository -import com.mulberry.ody.domain.repository.ody.MatesEtaRepository import com.mulberry.ody.domain.validator.AddressValidator import com.mulberry.ody.presentation.common.BaseViewModel import com.mulberry.ody.presentation.common.analytics.AnalyticsHelper diff --git a/android/app/src/main/java/com/mulberry/ody/presentation/login/LoginViewModel.kt b/android/app/src/main/java/com/mulberry/ody/presentation/login/LoginViewModel.kt index 7ae499969..44f21af3a 100644 --- a/android/app/src/main/java/com/mulberry/ody/presentation/login/LoginViewModel.kt +++ b/android/app/src/main/java/com/mulberry/ody/presentation/login/LoginViewModel.kt @@ -7,7 +7,6 @@ import com.mulberry.ody.domain.apiresult.onFailure import com.mulberry.ody.domain.apiresult.onNetworkError import com.mulberry.ody.domain.apiresult.suspendOnSuccess import com.mulberry.ody.domain.repository.ody.LoginRepository -import com.mulberry.ody.domain.repository.ody.MatesEtaRepository import com.mulberry.ody.presentation.common.BaseViewModel import com.mulberry.ody.presentation.common.analytics.AnalyticsHelper import com.mulberry.ody.presentation.common.analytics.logNetworkErrorEvent diff --git a/android/app/src/main/java/com/mulberry/ody/presentation/notification/FCMNotification.kt b/android/app/src/main/java/com/mulberry/ody/presentation/notification/FCMNotification.kt index c60386505..08db30078 100644 --- a/android/app/src/main/java/com/mulberry/ody/presentation/notification/FCMNotification.kt +++ b/android/app/src/main/java/com/mulberry/ody/presentation/notification/FCMNotification.kt @@ -21,113 +21,113 @@ import kotlinx.coroutines.launch import javax.inject.Inject class FCMNotification -@Inject -constructor( - private val context: Context, - private val odyDatastore: OdyDatastore, - private val notificationManager: NotificationManager, -) { - init { - createNotificationChannel() - } - - private fun createNotificationChannel() { - val channel = - NotificationChannel( - NOTIFICATION_CHANNEL_ID, - NOTIFICATION_CHANNEL_NAME, - NotificationManager.IMPORTANCE_HIGH, - ) - channel.description = NOTIFICATION_DESCRIPTION - - notificationManager.createNotificationChannel(channel) - } - - fun showNotification( - type: FCMNotificationType, - nickname: String, - meetingId: String, - meetingName: String, + @Inject + constructor( + private val context: Context, + private val odyDatastore: OdyDatastore, + private val notificationManager: NotificationManager, ) { - CoroutineScope(Dispatchers.Default).launch { - if (isNotificationBlock(type)) { - return@launch - } - - val message = getNotificationMessage(type, nickname, meetingName) - val pendingIntent = getPendingIntent(type, meetingId) - showNotification(message, pendingIntent) + init { + createNotificationChannel() } - } - private suspend fun isNotificationBlock(type: FCMNotificationType): Boolean { - if (type == FCMNotificationType.DEPARTURE_REMINDER && !odyDatastore.getIsNotificationOn(type).first()) { - return true + private fun createNotificationChannel() { + val channel = + NotificationChannel( + NOTIFICATION_CHANNEL_ID, + NOTIFICATION_CHANNEL_NAME, + NotificationManager.IMPORTANCE_HIGH, + ) + channel.description = NOTIFICATION_DESCRIPTION + + notificationManager.createNotificationChannel(channel) } - if (type == FCMNotificationType.ENTRY && !odyDatastore.getIsNotificationOn(type).first()) { - return true + + fun showNotification( + type: FCMNotificationType, + nickname: String, + meetingId: String, + meetingName: String, + ) { + CoroutineScope(Dispatchers.Default).launch { + if (isNotificationBlock(type)) { + return@launch + } + + val message = getNotificationMessage(type, nickname, meetingName) + val pendingIntent = getPendingIntent(type, meetingId) + showNotification(message, pendingIntent) + } } - return false - } - private fun getNotificationMessage( - type: FCMNotificationType, - nickname: String, - meetingName: String, - ): String = - when (type) { - FCMNotificationType.ENTRY -> context.getString(R.string.fcm_notification_entry, nickname) - FCMNotificationType.DEPARTURE_REMINDER -> context.getString(R.string.fcm_notification_departure_reminder, nickname) - FCMNotificationType.NUDGE -> context.getString(R.string.fcm_notification_nudge, nickname) - FCMNotificationType.ETA_NOTICE -> context.getString(R.string.fcm_notification_eta_notice, meetingName) + private suspend fun isNotificationBlock(type: FCMNotificationType): Boolean { + if (type == FCMNotificationType.DEPARTURE_REMINDER && !odyDatastore.getIsNotificationOn(type).first()) { + return true + } + if (type == FCMNotificationType.ENTRY && !odyDatastore.getIsNotificationOn(type).first()) { + return true + } + return false } - private fun getPendingIntent( - type: FCMNotificationType, - meetingId: String, - ): PendingIntent? { - val navigationTarget = + private fun getNotificationMessage( + type: FCMNotificationType, + nickname: String, + meetingName: String, + ): String = when (type) { - FCMNotificationType.ENTRY, FCMNotificationType.DEPARTURE_REMINDER -> NAVIGATE_TO_NOTIFICATION_LOG - FCMNotificationType.NUDGE, FCMNotificationType.ETA_NOTICE -> NAVIGATE_TO_ETA_DASHBOARD + FCMNotificationType.ENTRY -> context.getString(R.string.fcm_notification_entry, nickname) + FCMNotificationType.DEPARTURE_REMINDER -> context.getString(R.string.fcm_notification_departure_reminder, nickname) + FCMNotificationType.NUDGE -> context.getString(R.string.fcm_notification_nudge, nickname) + FCMNotificationType.ETA_NOTICE -> context.getString(R.string.fcm_notification_eta_notice, meetingName) } - val stackBuilder = TaskStackBuilder.create(context) - val parentIntent = MeetingsActivity.getIntent(context) - stackBuilder.addNextIntent(parentIntent) + private fun getPendingIntent( + type: FCMNotificationType, + meetingId: String, + ): PendingIntent? { + val navigationTarget = + when (type) { + FCMNotificationType.ENTRY, FCMNotificationType.DEPARTURE_REMINDER -> NAVIGATE_TO_NOTIFICATION_LOG + FCMNotificationType.NUDGE, FCMNotificationType.ETA_NOTICE -> NAVIGATE_TO_ETA_DASHBOARD + } - val meetingRoomIntent = MeetingRoomActivity.getIntent(context, meetingId.toLong(), navigationTarget) - stackBuilder.addNextIntent(meetingRoomIntent) + val stackBuilder = TaskStackBuilder.create(context) + val parentIntent = MeetingsActivity.getIntent(context) + stackBuilder.addNextIntent(parentIntent) - return stackBuilder.getPendingIntent( - NOTIFICATION_REQUEST_CODE, - PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, - ) - } + val meetingRoomIntent = MeetingRoomActivity.getIntent(context, meetingId.toLong(), navigationTarget) + stackBuilder.addNextIntent(meetingRoomIntent) - private fun showNotification( - msg: String?, - intent: PendingIntent?, - ) { - val notificationBuilder = - NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) - .setContentTitle(context.getString(R.string.app_name)) - .setSmallIcon(R.mipmap.ic_launcher) - .setContentText(msg) - .setContentIntent(intent) - .setAutoCancel(true) - .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) - .setVibrate(VIBRATE_PATTERN) + return stackBuilder.getPendingIntent( + NOTIFICATION_REQUEST_CODE, + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, + ) + } - notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()) - } + private fun showNotification( + msg: String?, + intent: PendingIntent?, + ) { + val notificationBuilder = + NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setContentTitle(context.getString(R.string.app_name)) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentText(msg) + .setContentIntent(intent) + .setAutoCancel(true) + .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) + .setVibrate(VIBRATE_PATTERN) - companion object { - private const val NOTIFICATION_ID = 0 - private const val NOTIFICATION_CHANNEL_NAME = "notification_channel_name" - private const val NOTIFICATION_DESCRIPTION = "notification_description_name" - private const val NOTIFICATION_CHANNEL_ID = "notification_id" - private const val NOTIFICATION_REQUEST_CODE = 1000 - private val VIBRATE_PATTERN: LongArray = longArrayOf(1, 1000) + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()) + } + + companion object { + private const val NOTIFICATION_ID = 0 + private const val NOTIFICATION_CHANNEL_NAME = "notification_channel_name" + private const val NOTIFICATION_DESCRIPTION = "notification_description_name" + private const val NOTIFICATION_CHANNEL_ID = "notification_id" + private const val NOTIFICATION_REQUEST_CODE = 1000 + private val VIBRATE_PATTERN: LongArray = longArrayOf(1, 1000) + } } -} diff --git a/android/app/src/test/java/com/mulberry/ody/fake/FakeMatesEtaRepository.kt b/android/app/src/test/java/com/mulberry/ody/fake/FakeMatesEtaRepository.kt index c04e525e3..211c4b31e 100644 --- a/android/app/src/test/java/com/mulberry/ody/fake/FakeMatesEtaRepository.kt +++ b/android/app/src/test/java/com/mulberry/ody/fake/FakeMatesEtaRepository.kt @@ -5,7 +5,6 @@ import com.mulberry.ody.domain.repository.ody.MatesEtaRepository import com.mulberry.ody.mateEtaInfo import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import java.time.LocalDateTime object FakeMatesEtaRepository : MatesEtaRepository { override fun fetchMatesEtaInfo(meetingId: Long): Flow {