diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/Notification.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/Notification.kt index c48bcdb5ef5..e58b855f666 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/model/Notification.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/model/Notification.kt @@ -31,6 +31,12 @@ data class Notification( @IgnoredOnParcel val isReviewNotification = noteType == WooNotificationType.PRODUCT_REVIEW + @IgnoredOnParcel + val isBlazeNotification = noteType == WooNotificationType.BLAZE_APPROVED_NOTE || + noteType == WooNotificationType.BLAZE_REJECTED_NOTE || + noteType == WooNotificationType.BLAZE_CANCELLED_NOTE || + noteType == WooNotificationType.BLAZE_PERFORMED_NOTE + /** * Notifications are grouped based on the notification type and the store the notification belongs to. * @@ -74,6 +80,11 @@ fun NotificationModel.getUniqueId(): Long { return when (this.type) { NotificationModel.Kind.STORE_ORDER -> this.meta?.ids?.order ?: 0L NotificationModel.Kind.COMMENT -> this.meta?.ids?.comment ?: 0L + NotificationModel.Kind.BLAZE_APPROVED_NOTE, + NotificationModel.Kind.BLAZE_REJECTED_NOTE, + NotificationModel.Kind.BLAZE_CANCELLED_NOTE, + NotificationModel.Kind.BLAZE_PERFORMED_NOTE -> this.meta?.ids?.campaignId ?: 0L + else -> 0L } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/notifications/WooNotificationType.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/notifications/WooNotificationType.kt index 23d50cf95ae..688f3bfa20b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/notifications/WooNotificationType.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/notifications/WooNotificationType.kt @@ -6,13 +6,20 @@ enum class WooNotificationType { NEW_ORDER, PRODUCT_REVIEW, LOCAL_REMINDER, - BLAZE + BLAZE_APPROVED_NOTE, + BLAZE_REJECTED_NOTE, + BLAZE_CANCELLED_NOTE, + BLAZE_PERFORMED_NOTE, } fun NotificationModel.getWooType(): WooNotificationType { return when (this.type) { NotificationModel.Kind.STORE_ORDER -> WooNotificationType.NEW_ORDER NotificationModel.Kind.COMMENT -> WooNotificationType.PRODUCT_REVIEW + NotificationModel.Kind.BLAZE_APPROVED_NOTE -> WooNotificationType.BLAZE_APPROVED_NOTE + NotificationModel.Kind.BLAZE_REJECTED_NOTE -> WooNotificationType.BLAZE_REJECTED_NOTE + NotificationModel.Kind.BLAZE_CANCELLED_NOTE -> WooNotificationType.BLAZE_CANCELLED_NOTE + NotificationModel.Kind.BLAZE_PERFORMED_NOTE -> WooNotificationType.BLAZE_PERFORMED_NOTE else -> WooNotificationType.LOCAL_REMINDER } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListViewModel.kt index 95b8ef26225..c0f99231dfa 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListViewModel.kt @@ -79,6 +79,14 @@ class BlazeCampaignListViewModel @Inject constructor( if (navArgs.isPostCampaignCreation) { showCampaignCelebrationIfNeeded() } + if (navArgs.campaignId != null) { + triggerEvent( + ShowCampaignDetails( + url = blazeUrlsHelper.buildCampaignDetailsUrl(navArgs.campaignId!!), + urlToTriggerExit = blazeUrlsHelper.buildCampaignsListUrl() + ) + ) + } launch { loadCampaigns(offset = 0) } @@ -109,14 +117,13 @@ class BlazeCampaignListViewModel @Inject constructor( } private fun onCampaignClicked(campaignId: String) { - val url = blazeUrlsHelper.buildCampaignDetailsUrl(campaignId) analyticsTrackerWrapper.track( stat = BLAZE_CAMPAIGN_DETAIL_SELECTED, properties = mapOf(AnalyticsTracker.KEY_BLAZE_SOURCE to BlazeFlowSource.CAMPAIGN_LIST.trackingName) ) triggerEvent( ShowCampaignDetails( - url = url, + url = blazeUrlsHelper.buildCampaignDetailsUrl(campaignId), urlToTriggerExit = blazeUrlsHelper.buildCampaignsListUrl() ) ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivity.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivity.kt index 48673194621..f5efbf9010b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivity.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivity.kt @@ -81,6 +81,8 @@ import com.woocommerce.android.ui.main.MainActivityViewModel.RestartActivityForP import com.woocommerce.android.ui.main.MainActivityViewModel.ShortcutOpenOrderCreation import com.woocommerce.android.ui.main.MainActivityViewModel.ShortcutOpenPayments import com.woocommerce.android.ui.main.MainActivityViewModel.ShowFeatureAnnouncement +import com.woocommerce.android.ui.main.MainActivityViewModel.ViewBlazeCampaignDetail +import com.woocommerce.android.ui.main.MainActivityViewModel.ViewBlazeCampaignList import com.woocommerce.android.ui.main.MainActivityViewModel.ViewMyStoreStats import com.woocommerce.android.ui.main.MainActivityViewModel.ViewOrderDetail import com.woocommerce.android.ui.main.MainActivityViewModel.ViewOrderList @@ -786,7 +788,7 @@ class MainActivity : intent.removeExtra(FIELD_REMOTE_NOTIFICATION) intent.removeExtra(FIELD_PUSH_ID) - viewModel.handleIncomingNotification(localPushId, notification) + viewModel.onPushNotificationTapped(localPushId, notification) } else if (localNotification != null) { intent.removeExtra(FIELD_LOCAL_NOTIFICATION) viewModel.onLocalNotificationTapped(localNotification) @@ -803,6 +805,8 @@ class MainActivity : is ViewOrderDetail -> showOrderDetail(event) is ViewReviewDetail -> showReviewDetail(event.uniqueId, launchedFromNotification = true) is ViewReviewList -> showReviewList() + is ViewBlazeCampaignDetail -> showBlazeCampaignList(event.campaignId, event.isOpenedFromPush) + ViewBlazeCampaignList -> showBlazeCampaignList(campaignId = null) is RestartActivityEvent -> onRestartActivityEvent(event) is ShowFeatureAnnouncement -> navigateToFeatureAnnouncement(event) is ViewUrlInWebView -> navigateToWebView(event) @@ -843,6 +847,18 @@ class MainActivity : observeBottomBarState() } + private fun showBlazeCampaignList(campaignId: String?, isOpenedFromPush: Boolean = false) { + binding.bottomNav.currentPosition = MORE + binding.bottomNav.active(MORE.position) + + navController.navigateSafely( + MoreMenuFragmentDirections.actionMoreMenuToBlazeCampaignListFragment( + campaignId = campaignId + ), + skipThrottling = isOpenedFromPush + ) + } + private fun observeNotificationsPermissionBarVisibility() { viewModel.isNotificationsPermissionCardVisible.observe(this) { isVisible -> if (isVisible) { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivityViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivityViewModel.kt index 9d0b29f078b..a3bebe4ef8f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivityViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/main/MainActivityViewModel.kt @@ -15,6 +15,13 @@ import com.woocommerce.android.model.FeatureAnnouncement import com.woocommerce.android.model.Notification import com.woocommerce.android.notifications.NotificationChannelType import com.woocommerce.android.notifications.UnseenReviewsCountHandler +import com.woocommerce.android.notifications.WooNotificationType.BLAZE_APPROVED_NOTE +import com.woocommerce.android.notifications.WooNotificationType.BLAZE_CANCELLED_NOTE +import com.woocommerce.android.notifications.WooNotificationType.BLAZE_PERFORMED_NOTE +import com.woocommerce.android.notifications.WooNotificationType.BLAZE_REJECTED_NOTE +import com.woocommerce.android.notifications.WooNotificationType.LOCAL_REMINDER +import com.woocommerce.android.notifications.WooNotificationType.NEW_ORDER +import com.woocommerce.android.notifications.WooNotificationType.PRODUCT_REVIEW import com.woocommerce.android.notifications.local.LocalNotificationType import com.woocommerce.android.notifications.local.LocalNotificationType.BLAZE_ABANDONED_CAMPAIGN_REMINDER import com.woocommerce.android.notifications.local.LocalNotificationType.BLAZE_NO_CAMPAIGN_REMINDER @@ -110,7 +117,7 @@ class MainActivityViewModel @Inject constructor( ) } - fun handleIncomingNotification(localPushId: Int, notification: Notification?) { + fun onPushNotificationTapped(localPushId: Int, notification: Notification?) { notification?.let { // update current selectSite based on the current notification val currentSite = selectedSite.get() @@ -119,8 +126,8 @@ class MainActivityViewModel @Inject constructor( changeSiteAndRestart(it.remoteSiteId, RestartActivityForPushNotification(localPushId, notification)) } else { when (localPushId) { - it.getGroupPushId() -> onGroupMessageOpened(it.channelType, it.remoteSiteId) - else -> onSingleNotificationOpened(localPushId, it) + it.getGroupPushId() -> onGroupMessageOpened(it) + else -> onSinglePushNotificationOpened(localPushId, it) } } } ?: run { @@ -171,29 +178,53 @@ class MainActivityViewModel @Inject constructor( } } - private fun onGroupMessageOpened(notificationChannelType: NotificationChannelType, remoteSiteId: Long) { - notificationHandler.markNotificationsOfTypeTapped(notificationChannelType) - notificationHandler.removeNotificationsOfTypeFromSystemsBar(notificationChannelType, remoteSiteId) - when (notificationChannelType) { + private fun onGroupMessageOpened(notification: Notification) { + notificationHandler.markNotificationsOfTypeTapped(notification.channelType) + notificationHandler.removeNotificationsOfTypeFromSystemsBar(notification.channelType, notification.remoteSiteId) + when (notification.channelType) { NotificationChannelType.NEW_ORDER -> triggerEvent(ViewOrderList) NotificationChannelType.REVIEW -> triggerEvent(ViewReviewList) - else -> triggerEvent(ViewMyStoreStats) + NotificationChannelType.OTHER -> if (notification.isBlazeNotification) { + triggerEvent(ViewBlazeCampaignList) + } else { + triggerEvent(ViewMyStoreStats) + } } } - private fun onSingleNotificationOpened(localPushId: Int, notification: Notification) { + private fun onSinglePushNotificationOpened(localPushId: Int, notification: Notification) { notificationHandler.markNotificationTapped(notification.remoteNoteId) notificationHandler.removeNotificationByNotificationIdFromSystemsBar(localPushId) - if (notification.channelType == NotificationChannelType.REVIEW) { - analyticsTrackerWrapper.track(REVIEW_OPEN) - triggerEvent(ViewReviewDetail(notification.uniqueId)) - } else if (notification.channelType == NotificationChannelType.NEW_ORDER) { - if (siteStore.getSiteBySiteId(notification.remoteSiteId) != null) { - triggerEvent(ViewOrderDetail(notification.uniqueId, notification.remoteNoteId)) - } else { - // the site does not exist locally, open order list - triggerEvent(ViewOrderList) + when (notification.noteType) { + NEW_ORDER -> { + when { + siteStore.getSiteBySiteId(notification.remoteSiteId) != null -> triggerEvent( + ViewOrderDetail( + notification.uniqueId, + notification.remoteNoteId + ) + ) + + else -> triggerEvent(ViewOrderList) + } } + + PRODUCT_REVIEW -> { + analyticsTrackerWrapper.track(REVIEW_OPEN) + triggerEvent(ViewReviewDetail(notification.uniqueId)) + } + + BLAZE_APPROVED_NOTE, + BLAZE_REJECTED_NOTE, + BLAZE_CANCELLED_NOTE, + BLAZE_PERFORMED_NOTE -> triggerEvent( + ViewBlazeCampaignDetail( + campaignId = notification.uniqueId.toString(), + isOpenedFromPush = true + ) + ) + + LOCAL_REMINDER -> error("Local reminder notification should not be handled here") } } @@ -314,6 +345,7 @@ class MainActivityViewModel @Inject constructor( data class ViewUrlInWebView( val url: String, ) : Event() + object ShortcutOpenPayments : Event() object ShortcutOpenOrderCreation : Event() object LaunchBlazeCampaignCreation : Event() @@ -330,6 +362,8 @@ class MainActivityViewModel @Inject constructor( data class ShowFeatureAnnouncement(val announcement: FeatureAnnouncement) : Event() data class ViewReviewDetail(val uniqueId: Long) : Event() data class ViewOrderDetail(val uniqueId: Long, val remoteNoteId: Long) : Event() + data class ViewBlazeCampaignDetail(val campaignId: String, val isOpenedFromPush: Boolean) : Event() + object ViewBlazeCampaignList : Event() data class ShowPrivacyPreferenceUpdatedFailed(val analyticsEnabled: Boolean) : Event() object ShowPrivacySettings : Event() data class ShowPrivacySettingsWithError(val requestedAnalyticsValue: RequestedAnalyticsValue) : Event() diff --git a/WooCommerce/src/main/res/navigation/nav_graph_main.xml b/WooCommerce/src/main/res/navigation/nav_graph_main.xml index 5a64cb374b9..e7777a93224 100644 --- a/WooCommerce/src/main/res/navigation/nav_graph_main.xml +++ b/WooCommerce/src/main/res/navigation/nav_graph_main.xml @@ -811,6 +811,11 @@ android:name="isPostCampaignCreation" android:defaultValue="false" app:argType="boolean" /> +