diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/fragment/NotificationsOnboardingFragment.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/fragment/NotificationsOnboardingFragment.kt index d1b1cefb29..d88284a1c9 100644 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/fragment/NotificationsOnboardingFragment.kt +++ b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/fragment/NotificationsOnboardingFragment.kt @@ -108,6 +108,9 @@ class NotificationsOnboardingFragment : Fragment() { ViewAction.RequestNotificationPermission -> { notificationPermissionDelegate?.requestNotificationPermission() } + is ViewAction.ShowDailyStudyRemindersIntervalStartHourPickerModal -> { + // TODO: ALTAPPS-1071 show modal + } } } diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/ui/NotificationsOnboardingScreen.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/ui/NotificationsOnboardingScreen.kt index 04cc52d3b2..bcd31da02e 100644 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/ui/NotificationsOnboardingScreen.kt +++ b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/notification_onboarding/ui/NotificationsOnboardingScreen.kt @@ -52,10 +52,10 @@ fun NotificationsOnboardingScreen( onNewMessage: (NotificationsOnboardingFeature.Message) -> Unit ) { val onAllowNotificationsClick by rememberUpdatedState { - onNewMessage(NotificationsOnboardingFeature.Message.AllowNotificationClicked) + onNewMessage(NotificationsOnboardingFeature.Message.AllowNotificationsClicked) } val onRemindMeLaterClick by rememberUpdatedState { - onNewMessage(NotificationsOnboardingFeature.Message.RemindMeLaterClicked) + onNewMessage(NotificationsOnboardingFeature.Message.NotNowClicked) } Column( modifier = Modifier @@ -124,7 +124,7 @@ fun NotificationsOnboardingButtons( modifier = Modifier.fillMaxWidth() ) { Text( - text = stringResource(id = R.string.notifications_onboarding_button_later) + text = stringResource(id = R.string.notifications_onboarding_button_not_now) ) } } diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/stage_implementation/view/fragment/StageStepWrapperFragment.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/stage_implementation/view/fragment/StageStepWrapperFragment.kt index 8ee6c4b0db..37aad19abc 100644 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/stage_implementation/view/fragment/StageStepWrapperFragment.kt +++ b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/stage_implementation/view/fragment/StageStepWrapperFragment.kt @@ -18,7 +18,6 @@ import org.hyperskill.app.android.step.view.fragment.StepFragment import org.hyperskill.app.android.step.view.model.StepCompletionHost import org.hyperskill.app.android.step.view.model.StepCompletionView import org.hyperskill.app.android.step_practice.view.fragment.StepPracticeDetailsFragment -import org.hyperskill.app.android.step_quiz.view.dialog.RequestDailyStudyReminderDialogFragment import org.hyperskill.app.android.step_quiz.view.factory.StepQuizFragmentFactory import org.hyperskill.app.step.domain.model.Step import org.hyperskill.app.step.domain.model.StepRoute @@ -42,7 +41,6 @@ class StageStepWrapperFragment : Fragment(R.layout.fragment_stage_step_wrapper), ReduxView, StepCompletionHost, - RequestDailyStudyReminderDialogFragment.Callback, ShareStreakDialogFragment.Callback { companion object { @@ -83,12 +81,7 @@ class StageStepWrapperFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) injectComponent() - stepDelegate = StepDelegate( - fragment = this, - onRequestDailyStudyRemindersPermissionResult = { isGranted -> - onNewMessage(StepCompletionFeature.Message.RequestDailyStudyRemindersPermissionResult(isGranted)) - } - ) + stepDelegate = StepDelegate(fragment = this) } private fun injectComponent() { @@ -161,10 +154,6 @@ class StageStepWrapperFragment : stepViewModel.onNewMessage(StepFeature.Message.StepCompletionMessage(message)) } - override fun onPermissionResult(isGranted: Boolean) { - stepDelegate?.onPermissionResult(isGranted) - } - override fun onShareStreakBottomSheetShown(streak: Int) { stepViewModel.onShareStreakBottomSheetShown(streak) } diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/delegate/StepDelegate.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/delegate/StepDelegate.kt index 082585f39a..f016290f73 100644 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/delegate/StepDelegate.kt +++ b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/delegate/StepDelegate.kt @@ -4,39 +4,28 @@ import android.content.ActivityNotFoundException import android.content.Context import android.util.Log import androidx.annotation.DrawableRes -import androidx.core.app.NotificationManagerCompat import androidx.fragment.app.Fragment import org.hyperskill.app.R import org.hyperskill.app.android.core.extensions.ShareUtils -import org.hyperskill.app.android.core.extensions.checkNotificationChannelAvailability import org.hyperskill.app.android.core.view.ui.navigation.requireRouter import org.hyperskill.app.android.databinding.ErrorNoConnectionWithButtonBinding import org.hyperskill.app.android.main.view.ui.navigation.MainScreen import org.hyperskill.app.android.main.view.ui.navigation.MainScreenRouter import org.hyperskill.app.android.main.view.ui.navigation.Tabs import org.hyperskill.app.android.main.view.ui.navigation.switch -import org.hyperskill.app.android.notification.model.HyperskillNotificationChannel -import org.hyperskill.app.android.notification.permission.NotificationPermissionDelegate import org.hyperskill.app.android.share_streak.fragment.ShareStreakDialogFragment import org.hyperskill.app.android.step.view.dialog.TopicPracticeCompletedBottomSheet import org.hyperskill.app.android.step.view.screen.StepScreen import org.hyperskill.app.android.step_quiz.view.dialog.CompletedStepOfTheDayDialogFragment -import org.hyperskill.app.android.step_quiz.view.dialog.RequestDailyStudyReminderDialogFragment import org.hyperskill.app.android.view.base.ui.extension.snackbar import org.hyperskill.app.step.presentation.StepFeature import org.hyperskill.app.step_completion.presentation.StepCompletionFeature import ru.nobird.android.view.base.ui.extension.showIfNotExists class StepDelegate( - private val fragment: TFragment, - private val onRequestDailyStudyRemindersPermissionResult: (Boolean) -> Unit -) : RequestDailyStudyReminderDialogFragment.Callback - where TFragment : Fragment, - TFragment : RequestDailyStudyReminderDialogFragment.Callback, - TFragment : ShareStreakDialogFragment.Callback { - - private val notificationPermissionDelegate: NotificationPermissionDelegate = - NotificationPermissionDelegate(fragment, ::onNotificationPermissionResult) + private val fragment: TFragment +) where TFragment : Fragment, + TFragment : ShareStreakDialogFragment.Callback { fun init(errorBinding: ErrorNoConnectionWithButtonBinding, onNewMessage: (StepFeature.Message) -> Unit) { onNewMessage(StepFeature.Message.ViewedEventMessage) @@ -80,10 +69,6 @@ class StepDelegate( TopicPracticeCompletedBottomSheet.Tag ) } - StepCompletionFeature.Action.ViewAction.RequestDailyStudyRemindersPermission -> { - RequestDailyStudyReminderDialogFragment.newInstance() - .showIfNotExists(fragment.childFragmentManager, RequestDailyStudyReminderDialogFragment.TAG) - } is StepCompletionFeature.Action.ViewAction.ShowProblemOfDaySolvedModal -> { CompletedStepOfTheDayDialogFragment .newInstance( @@ -108,35 +93,6 @@ class StepDelegate( } } - override fun onPermissionResult(isGranted: Boolean) { - if (isGranted) { - notificationPermissionDelegate.requestNotificationPermission() - } else { - onRequestDailyStudyRemindersPermissionResult(false) - } - } - - private fun onNotificationPermissionResult(result: NotificationPermissionDelegate.Result) { - when (result) { - NotificationPermissionDelegate.Result.GRANTED -> { - onNotificationPermissionGranted() - } - NotificationPermissionDelegate.Result.DENIED, - NotificationPermissionDelegate.Result.DONT_ASK -> { - onRequestDailyStudyRemindersPermissionResult(false) - } - } - } - - private fun onNotificationPermissionGranted() { - onRequestDailyStudyRemindersPermissionResult(true) - val context = fragment.context - if (context != null) { - NotificationManagerCompat.from(context) - .checkNotificationChannelAvailability(context, HyperskillNotificationChannel.DailyReminder) - } - } - @DrawableRes private fun getShareStreakDrawableRes(streak: Int): Int = when (streak) { diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/fragment/StepFragment.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/fragment/StepFragment.kt index 71709b3a35..e302accf32 100644 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/fragment/StepFragment.kt +++ b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step/view/fragment/StepFragment.kt @@ -16,7 +16,6 @@ import org.hyperskill.app.android.step.view.delegate.StepDelegate import org.hyperskill.app.android.step.view.model.StepCompletionHost import org.hyperskill.app.android.step.view.model.StepCompletionView import org.hyperskill.app.android.step_practice.view.fragment.StepPracticeFragment -import org.hyperskill.app.android.step_quiz.view.dialog.RequestDailyStudyReminderDialogFragment import org.hyperskill.app.android.step_theory.view.fragment.StepTheoryFragment import org.hyperskill.app.step.domain.model.Step import org.hyperskill.app.step.domain.model.StepRoute @@ -31,7 +30,6 @@ class StepFragment : Fragment(R.layout.fragment_step), ReduxView, StepCompletionHost, - RequestDailyStudyReminderDialogFragment.Callback, ShareStreakDialogFragment.Callback { companion object { @@ -59,12 +57,7 @@ class StepFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) injectComponent() - stepDelegate = StepDelegate( - fragment = this, - onRequestDailyStudyRemindersPermissionResult = { isGranted -> - onNewMessage(StepCompletionFeature.Message.RequestDailyStudyRemindersPermissionResult(isGranted)) - } - ) + stepDelegate = StepDelegate(fragment = this) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -129,10 +122,6 @@ class StepFragment : ) } - override fun onPermissionResult(isGranted: Boolean) { - stepDelegate?.onPermissionResult(isGranted) - } - override fun onShareStreakBottomSheetShown(streak: Int) { stepViewModel.onShareStreakBottomSheetShown(streak) } diff --git a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step_quiz/view/dialog/RequestDailyStudyReminderDialogFragment.kt b/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step_quiz/view/dialog/RequestDailyStudyReminderDialogFragment.kt deleted file mode 100644 index e073ca14d0..0000000000 --- a/androidHyperskillApp/src/main/java/org/hyperskill/app/android/step_quiz/view/dialog/RequestDailyStudyReminderDialogFragment.kt +++ /dev/null @@ -1,34 +0,0 @@ -package org.hyperskill.app.android.step_quiz.view.dialog - -import android.app.Dialog -import android.os.Bundle -import androidx.fragment.app.DialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder - -class RequestDailyStudyReminderDialogFragment : DialogFragment() { - - companion object { - const val TAG: String = "RequestDailyStudyReminderDialogFragment" - - fun newInstance(): RequestDailyStudyReminderDialogFragment = - RequestDailyStudyReminderDialogFragment() - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = - MaterialAlertDialogBuilder(requireContext()) - .setTitle(org.hyperskill.app.R.string.after_daily_step_completed_dialog_title) - .setMessage(org.hyperskill.app.R.string.after_daily_step_completed_dialog_text) - .setPositiveButton(org.hyperskill.app.R.string.ok) { dialog, _ -> - (parentFragment as Callback).onPermissionResult(true) - dialog.dismiss() - } - .setNegativeButton(org.hyperskill.app.R.string.later) { dialog, _ -> - (parentFragment as Callback).onPermissionResult(false) - dialog.dismiss() - } - .show() - - interface Callback { - fun onPermissionResult(isGranted: Boolean) - } -} \ No newline at end of file diff --git a/iosHyperskillApp/iosHyperskillApp/Sources/Models/Constants/Strings.swift b/iosHyperskillApp/iosHyperskillApp/Sources/Models/Constants/Strings.swift index 8d6312ae35..086c6ae7a4 100644 --- a/iosHyperskillApp/iosHyperskillApp/Sources/Models/Constants/Strings.swift +++ b/iosHyperskillApp/iosHyperskillApp/Sources/Models/Constants/Strings.swift @@ -75,11 +75,6 @@ enum Strings { enum Step { static let startPracticing = sharedStrings.step_start_practicing_text.localized() static let theory = sharedStrings.step_theory_text.localized() - - enum RequestDailyNotificationsAlert { - static let title = sharedStrings.after_daily_step_completed_dialog_title.localized() - static let text = sharedStrings.after_daily_step_completed_dialog_text.localized() - } } // MARK: - StepQuiz - @@ -477,7 +472,7 @@ enum Strings { static let subtitle = sharedStrings.notifications_onboarding_description.localized() static let buttonPrimary = sharedStrings.notifications_onboarding_button_allow.localized() - static let buttonSecondary = sharedStrings.notifications_onboarding_button_later.localized() + static let buttonSecondary = sharedStrings.notifications_onboarding_button_not_now.localized() } // MARK: - FirstProblemOnboarding - diff --git a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/NotificationsOnboardingViewModel.swift b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/NotificationsOnboardingViewModel.swift index a9f98ca8c8..486bda8473 100644 --- a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/NotificationsOnboardingViewModel.swift +++ b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/NotificationsOnboardingViewModel.swift @@ -2,7 +2,7 @@ import Foundation import shared final class NotificationsOnboardingViewModel: FeatureViewModel< - NotificationsOnboardingFeature.State, + NotificationsOnboardingFeature.ViewState, NotificationsOnboardingFeatureMessage, NotificationsOnboardingFeatureActionViewAction > { @@ -19,18 +19,18 @@ final class NotificationsOnboardingViewModel: FeatureViewModel< } override func shouldNotifyStateDidChange( - oldState: NotificationsOnboardingFeature.State, - newState: NotificationsOnboardingFeature.State + oldState: NotificationsOnboardingFeature.ViewState, + newState: NotificationsOnboardingFeature.ViewState ) -> Bool { false } func doPrimaryAction() { - onNewMessage(NotificationsOnboardingFeatureMessageAllowNotificationClicked()) + onNewMessage(NotificationsOnboardingFeatureMessageAllowNotificationsClicked()) } func doSecondaryAction() { - onNewMessage(NotificationsOnboardingFeatureMessageRemindMeLaterClicked()) + onNewMessage(NotificationsOnboardingFeatureMessageNotNowClicked()) } func doRequestNotificationPermission() { diff --git a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/Views/NotificationsOnboardingView.swift b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/Views/NotificationsOnboardingView.swift index c4730ed1c8..ff5fd677aa 100644 --- a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/Views/NotificationsOnboardingView.swift +++ b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/NotificationsOnboarding/Views/NotificationsOnboardingView.swift @@ -45,6 +45,8 @@ private extension NotificationsOnboardingView { viewModel.doCompleteOnboarding() case .requestNotificationPermission: viewModel.doRequestNotificationPermission() + case .showDailyStudyRemindersIntervalStartHourPickerModal: + #warning("TODO: ALTAPPS-1070 handle this") } } } diff --git a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepAssembly.swift b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepAssembly.swift index d7fc9a77c7..7a6a503d1f 100644 --- a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepAssembly.swift +++ b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepAssembly.swift @@ -55,7 +55,6 @@ final class StepAssembly: Assembly, UIKitAssembly { private func makeViewModel() -> StepViewModel { let commonComponent = AppGraphBridge.sharedAppGraph.commonComponent let stepComponent = AppGraphBridge.sharedAppGraph.buildStepComponent(stepRoute: stepRoute) - let notificationComponent = AppGraphBridge.sharedAppGraph.buildNotificationComponent() return StepViewModel( stepRoute: stepRoute, @@ -64,10 +63,6 @@ final class StepAssembly: Assembly, UIKitAssembly { resourceProvider: commonComponent.resourceProvider, commentThreadTitleMapper: stepComponent.commentThreadTitleMapper ), - notificationService: NotificationsService( - notificationInteractor: notificationComponent.notificationInteractor - ), - notificationsRegistrationService: .shared, feature: stepComponent.stepFeature ) } diff --git a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepViewModel.swift b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepViewModel.swift index 9afe5b0cc5..18251d14e6 100644 --- a/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepViewModel.swift +++ b/iosHyperskillApp/iosHyperskillApp/Sources/Modules/Step/StepViewModel.swift @@ -10,9 +10,6 @@ final class StepViewModel: FeatureViewModel -) : ReduxFlowViewModel(viewContainer) \ No newline at end of file + viewContainer: FlowView +) : ReduxFlowViewModel(viewContainer) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticPart.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticPart.kt index 196f36e078..d520b76f94 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticPart.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticPart.kt @@ -17,7 +17,6 @@ enum class HyperskillAnalyticPart(val partName: String) { CHALLENGE_CARD("challenge_card"), REPEAT_NEXT_TOPIC("repeat_next_topic"), REPEAT_TOPIC("repeat_topic"), - DAILY_NOTIFICATIONS_NOTICE("daily_notifications_notice"), STEP_HINTS("step_hints"), DAILY_STEP_COMPLETED_MODAL("daily_step_completed_modal"), TOPIC_COMPLETED_MODAL("topic_completed_modal"), @@ -40,5 +39,6 @@ enum class HyperskillAnalyticPart(val partName: String) { SHARE_STREAK_MODAL("share_streak_modal"), LEADERBOARD_DAY_TAB("leaderboard_day_tab"), LEADERBOARD_WEEK_TAB("leaderboard_week_tab"), - SEARCH_RESULTS("search_results") + SEARCH_RESULTS("search_results"), + DAILY_STUDY_REMINDERS_HOUR_INTERVAL_PICKER_MODAL("daily_study_reminders_hour_interval_picker_modal") } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticTarget.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticTarget.kt index 91c8c45942..925a8947c1 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticTarget.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/analytic/domain/model/hyperskill/HyperskillAnalyticTarget.kt @@ -14,7 +14,6 @@ enum class HyperskillAnalyticTarget(val targetName: String) { RUN("run"), ALLOW("allow"), DENY("deny"), - LATER("later"), OK("ok"), CANCEL("cancel"), DELETE("delete"), @@ -34,7 +33,6 @@ enum class HyperskillAnalyticTarget(val targetName: String) { SETTINGS("settings"), DAILY_STUDY_REMINDS("daily_study_reminds"), DAILY_STUDY_REMINDS_TIME("daily_study_reminds_time"), - DAILY_NOTIFICATIONS_NOTICE("daily_notifications_notice"), DAILY_NOTIFICATION("daily_notification"), CONTINUE("continue"), RELOAD("reload"), @@ -97,7 +95,7 @@ enum class HyperskillAnalyticTarget(val targetName: String) { ALLOW_NOTIFICATIONS("allow_notifications"), KEEP_LEARNING("keep_learning"), START_LEARNING("start_learning"), - REMIND_ME_LATER("remind_me_later"), + NOT_NOW("not_now"), FULL_SCREEN_CODE_EDITOR("full_screen_code_editor"), CODE_INPUT_ACCESSORY_BUTTON("code_input_accessory_button"), SHARE_YOUR_STREAK("share_your_streak"), @@ -108,5 +106,7 @@ enum class HyperskillAnalyticTarget(val targetName: String) { DAY("day"), WEEK("week"), LEADERBOARD_ITEM("leaderboard_item"), - TOPIC("topic") + TOPIC("topic"), + DAILY_STUDY_REMINDERS_HOUR_INTERVAL_PICKER_MODAL("daily_study_reminders_hour_interval_picker_modal"), + CONFIRM("confirm") } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheDataSourceImpl.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheDataSourceImpl.kt index ceb494a63d..215a533645 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheDataSourceImpl.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheDataSourceImpl.kt @@ -117,21 +117,4 @@ class NotificationCacheDataSourceImpl( resourceProvider.getString(strings.notification14_text) ) ) - - override fun getLastTimeUserAskedToEnableDailyReminders(): Long? = - settings.getLongOrNull(NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_LAST_TIME_USER_ASKED_TO_ENABLE) - - override fun setLastTimeUserAskedToEnableDailyReminders(timestamp: Long) { - settings.putLong( - NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_LAST_TIME_USER_ASKED_TO_ENABLE, - timestamp - ) - settings.putLong( - NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_USER_ASKED_TO_ENABLE_COUNT, - getUserAskedToEnableDailyRemindersCount() + 1 - ) - } - - override fun getUserAskedToEnableDailyRemindersCount(): Long = - settings.getLong(NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_USER_ASKED_TO_ENABLE_COUNT, 0) } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheKeyValues.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheKeyValues.kt index 00be25a021..7cbbf14ae1 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheKeyValues.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/cache/NotificationCacheKeyValues.kt @@ -6,9 +6,5 @@ internal object NotificationCacheKeyValues { const val DAILY_STUDY_REMINDERS_ENABLED = "notifications_daily_reminder_enabled" const val DAILY_STUDY_REMINDERS_START_HOUR = "notifications_daily_reminder_start_hour" const val DAILY_STUDY_REMINDERS_START_HOUR_DEFAULT = 20 - const val DAILY_STUDY_REMINDERS_START_HOUR_AFTER_STEP_SOLVED = 12 - const val DAILY_STUDY_REMINDERS_LAST_TIME_USER_ASKED_TO_ENABLE = - "notifications_last_time_user_asked_to_enable_daily_reminders" - const val DAILY_STUDY_REMINDERS_USER_ASKED_TO_ENABLE_COUNT = - "notifications_user_asked_to_enable_daily_reminders_count" + const val DAILY_STUDY_REMINDERS_START_HOUR_ONBOARDING = 12 } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/repository/NotificationRepositoryImpl.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/repository/NotificationRepositoryImpl.kt index 6ec45c24f4..e1922013fe 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/repository/NotificationRepositoryImpl.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/repository/NotificationRepositoryImpl.kt @@ -37,14 +37,4 @@ class NotificationRepositoryImpl( override fun getRandomDailyStudyRemindersNotificationDescription(): NotificationDescription = notificationCacheDataSource.getRandomDailyStudyRemindersNotificationDescription() - - override fun getLastTimeUserAskedToEnableDailyReminders(): Long? = - notificationCacheDataSource.getLastTimeUserAskedToEnableDailyReminders() - - override fun setLastTimeUserAskedToEnableDailyReminders(timestamp: Long) { - notificationCacheDataSource.setLastTimeUserAskedToEnableDailyReminders(timestamp) - } - - override fun getUserAskedToEnableDailyRemindersCount(): Long = - notificationCacheDataSource.getUserAskedToEnableDailyRemindersCount() } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/source/NotificationCacheDataSource.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/source/NotificationCacheDataSource.kt index f2fe5484d9..92555aca05 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/source/NotificationCacheDataSource.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/data/source/NotificationCacheDataSource.kt @@ -16,8 +16,4 @@ interface NotificationCacheDataSource { fun setDailyStudyRemindersIntervalStartHour(hour: Int) fun getRandomDailyStudyRemindersNotificationDescription(): NotificationDescription - - fun getLastTimeUserAskedToEnableDailyReminders(): Long? - fun setLastTimeUserAskedToEnableDailyReminders(timestamp: Long) - fun getUserAskedToEnableDailyRemindersCount(): Long } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/interactor/NotificationInteractor.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/interactor/NotificationInteractor.kt index 1486ce51b4..4721d8aa85 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/interactor/NotificationInteractor.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/interactor/NotificationInteractor.kt @@ -1,7 +1,5 @@ package org.hyperskill.app.notification.local.domain.interactor -import kotlin.time.DurationUnit -import kotlin.time.toDuration import kotlinx.datetime.Clock import kotlinx.datetime.TimeZone import kotlinx.datetime.atTime @@ -13,18 +11,14 @@ import org.hyperskill.app.notification.local.domain.flow.DailyStudyRemindersEnab import org.hyperskill.app.notification.local.domain.repository.NotificationRepository import org.hyperskill.app.profile.domain.repository.CurrentProfileStateRepository import org.hyperskill.app.profile.domain.repository.ProfileRepository -import org.hyperskill.app.step_quiz.domain.repository.SubmissionRepository class NotificationInteractor( private val notificationRepository: NotificationRepository, - private val submissionRepository: SubmissionRepository, private val dailyStudyRemindersEnabledFlow: DailyStudyRemindersEnabledFlow, private val currentProfileStateRepository: CurrentProfileStateRepository, private val profileRepository: ProfileRepository ) { companion object { - private val TWO_DAYS_IN_MILLIS = 2.toDuration(DurationUnit.DAYS).inWholeMilliseconds - private const val MAX_USER_ASKED_TO_ENABLE_DAILY_REMINDERS_COUNT = 3 private const val UTC_TIME_ZONE_ID = "UTC" } @@ -57,31 +51,6 @@ class NotificationInteractor( fun getRandomDailyStudyRemindersNotificationDescription(): NotificationDescription = notificationRepository.getRandomDailyStudyRemindersNotificationDescription() - fun isRequiredToAskUserToEnableDailyReminders(): Boolean { - if (notificationRepository.isDailyStudyRemindersEnabled()) { - return false - } - - val isFirstStepSolved = submissionRepository.getSolvedStepsCount() >= 1L - - val lastTimeAsked = notificationRepository.getLastTimeUserAskedToEnableDailyReminders() ?: return true - val isAskedAtLeastTwoDaysAgo = (lastTimeAsked + TWO_DAYS_IN_MILLIS) <= Clock.System.now().toEpochMilliseconds() - - val isNotReachedMaxUserAskedCount = - getUserAskedToEnableDailyRemindersCount() < MAX_USER_ASKED_TO_ENABLE_DAILY_REMINDERS_COUNT - - return isFirstStepSolved && isAskedAtLeastTwoDaysAgo && isNotReachedMaxUserAskedCount - } - - fun updateLastTimeUserAskedToEnableDailyReminders() { - notificationRepository.setLastTimeUserAskedToEnableDailyReminders( - Clock.System.now().toEpochMilliseconds() - ) - } - - private fun getUserAskedToEnableDailyRemindersCount(): Long = - notificationRepository.getUserAskedToEnableDailyRemindersCount() - /** * Sets the daily study reminder notification time & set current timeZone * diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/repository/NotificationRepository.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/repository/NotificationRepository.kt index f566fb51b4..d7f01aacea 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/repository/NotificationRepository.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/domain/repository/NotificationRepository.kt @@ -16,8 +16,4 @@ interface NotificationRepository { fun setDailyStudyRemindersIntervalStartHour(hour: Int) fun getRandomDailyStudyRemindersNotificationDescription(): NotificationDescription - - fun getLastTimeUserAskedToEnableDailyReminders(): Long? - fun setLastTimeUserAskedToEnableDailyReminders(timestamp: Long) - fun getUserAskedToEnableDailyRemindersCount(): Long } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/injection/NotificationComponentImpl.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/injection/NotificationComponentImpl.kt index 14dba11716..6fa709b01e 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/injection/NotificationComponentImpl.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notification/local/injection/NotificationComponentImpl.kt @@ -21,7 +21,6 @@ class NotificationComponentImpl(appGraph: AppGraph) : NotificationComponent { override val notificationInteractor: NotificationInteractor = NotificationInteractor( notificationRepository, - appGraph.submissionDataComponent.submissionRepository, appGraph.notificationFlowDataComponent.dailyStudyRemindersEnabledFlow, profileDataComponent.currentProfileStateRepository, profileDataComponent.profileRepository diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingAnalyticParams.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingAnalyticParams.kt new file mode 100644 index 0000000000..77bae9e683 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingAnalyticParams.kt @@ -0,0 +1,5 @@ +package org.hyperskill.app.notifications_onboarding.domain.analytic + +internal object NotificationsOnboardingAnalyticParams { + const val PARAM_START_HOUR = "start_hour" +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent.kt similarity index 62% rename from shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent.kt rename to shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent.kt index 3e34926405..e145aeaa3a 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent.kt @@ -15,14 +15,29 @@ import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTar * "route": "/onboarding/notifications", * "action": "click", * "part": "main", - * "target": "allow_notifications" + * "target": "allow_notifications", + * "context": + * { + * "start_hour": 12 + * } * } * ``` + * * @see HyperskillAnalyticEvent */ -object NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent : HyperskillAnalyticEvent( +class NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent( + private val selectedDailyStudyRemindersStartHour: Int +) : HyperskillAnalyticEvent( route = HyperskillAnalyticRoute.Onboarding.Notifications, action = HyperskillAnalyticAction.CLICK, part = HyperskillAnalyticPart.MAIN, target = HyperskillAnalyticTarget.ALLOW_NOTIFICATIONS -) \ No newline at end of file +) { + override val params: Map + get() = super.params + + mapOf( + PARAM_CONTEXT to mapOf( + NotificationsOnboardingAnalyticParams.PARAM_START_HOUR to selectedDailyStudyRemindersStartHour + ) + ) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent.kt new file mode 100644 index 0000000000..b9e441ffd1 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent.kt @@ -0,0 +1,43 @@ +package org.hyperskill.app.notifications_onboarding.domain.analytic + +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget + +/** + * Represents click on the daily study reminds formatted time button analytic event. + * + * JSON payload: + * ``` + * { + * "route": "/onboarding/notifications", + * "action": "click", + * "part": "main", + * "target": "daily_study_reminds_time", + * "context": + * { + * "start_hour": 12 + * } + * } + * ``` + * + * @see HyperskillAnalyticEvent + */ +class NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent( + private val currentDailyStudyRemindersStartHour: Int +) : HyperskillAnalyticEvent( + route = HyperskillAnalyticRoute.Onboarding.Notifications, + action = HyperskillAnalyticAction.CLICK, + part = HyperskillAnalyticPart.MAIN, + target = HyperskillAnalyticTarget.DAILY_STUDY_REMINDS_TIME +) { + override val params: Map + get() = super.params + + mapOf( + PARAM_CONTEXT to mapOf( + NotificationsOnboardingAnalyticParams.PARAM_START_HOUR to currentDailyStudyRemindersStartHour + ) + ) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent.kt similarity index 82% rename from shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent.kt rename to shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent.kt index 82df3af657..1292694ef7 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent.kt @@ -15,14 +15,15 @@ import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTar * "route": "/onboarding/notifications", * "action": "click", * "part": "main", - * "target": "remind_me_later" + * "target": "not_now" * } * ``` + * * @see HyperskillAnalyticEvent */ -object NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent : HyperskillAnalyticEvent( +object NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent : HyperskillAnalyticEvent( route = HyperskillAnalyticRoute.Onboarding.Notifications, action = HyperskillAnalyticAction.CLICK, part = HyperskillAnalyticPart.MAIN, - target = HyperskillAnalyticTarget.REMIND_ME_LATER + target = HyperskillAnalyticTarget.NOT_NOW ) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent.kt new file mode 100644 index 0000000000..ed8d0a44d5 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent.kt @@ -0,0 +1,43 @@ +package org.hyperskill.app.notifications_onboarding.domain.analytic + +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget + +/** + * Represents a click on the "Confirm" button of the daily study reminders hour interval picker modal analytic event. + * + * JSON payload: + * ``` + * { + * "route": "/onboarding/notifications", + * "action": "click", + * "part": "daily_study_reminders_hour_interval_picker_modal", + * "target": "confirm", + * "context": + * { + * "start_hour": 12 + * } + * } + * ``` + * + * @see HyperskillAnalyticEvent + */ +class NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent( + private val selectedDailyStudyRemindersStartHour: Int +) : HyperskillAnalyticEvent( + route = HyperskillAnalyticRoute.Onboarding.Notifications, + action = HyperskillAnalyticAction.CLICK, + part = HyperskillAnalyticPart.DAILY_STUDY_REMINDERS_HOUR_INTERVAL_PICKER_MODAL, + target = HyperskillAnalyticTarget.CONFIRM +) { + override val params: Map + get() = super.params + + mapOf( + PARAM_CONTEXT to mapOf( + NotificationsOnboardingAnalyticParams.PARAM_START_HOUR to selectedDailyStudyRemindersStartHour + ) + ) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent.kt new file mode 100644 index 0000000000..91e82b5c6a --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent.kt @@ -0,0 +1,30 @@ +package org.hyperskill.app.notifications_onboarding.domain.analytic + +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget + +/** + * Represents a hidden analytic event of the daily study reminders hour interval picker modal. + * + * JSON payload: + * ``` + * { + * "route": "/onboarding/notifications", + * "action": "hidden", + * "part": "daily_study_reminders_hour_interval_picker_modal", + * "target": "close" + * } + * ``` + * + * @see HyperskillAnalyticEvent + */ +object NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent : + HyperskillAnalyticEvent( + route = HyperskillAnalyticRoute.Onboarding.Notifications, + action = HyperskillAnalyticAction.HIDDEN, + part = HyperskillAnalyticPart.DAILY_STUDY_REMINDERS_HOUR_INTERVAL_PICKER_MODAL, + target = HyperskillAnalyticTarget.CLOSE + ) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent.kt new file mode 100644 index 0000000000..deaa44a0d8 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent.kt @@ -0,0 +1,30 @@ +package org.hyperskill.app.notifications_onboarding.domain.analytic + +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute +import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget + +/** + * Represents a shown analytic event of the daily study reminders hour interval picker modal. + * + * JSON payload: + * ``` + * { + * "route": "/onboarding/notifications", + * "action": "shown", + * "part": "modal", + * "target": "daily_study_reminders_hour_interval_picker_modal" + * } + * ``` + * + * @see HyperskillAnalyticEvent + */ +object NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent : + HyperskillAnalyticEvent( + route = HyperskillAnalyticRoute.Onboarding.Notifications, + action = HyperskillAnalyticAction.SHOWN, + part = HyperskillAnalyticPart.MODAL, + target = HyperskillAnalyticTarget.DAILY_STUDY_REMINDERS_HOUR_INTERVAL_PICKER_MODAL + ) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticsEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticEvent.kt similarity index 90% rename from shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticsEvent.kt rename to shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticEvent.kt index a46ede32a1..bd947b8e9f 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticsEvent.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/domain/analytic/NotificationsOnboardingViewedHyperskillAnalyticEvent.kt @@ -14,7 +14,8 @@ import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRou * "action": "view" * } * ``` + * * @see HyperskillAnalyticEvent */ -object NotificationsOnboardingViewedHyperskillAnalyticsEvent : +object NotificationsOnboardingViewedHyperskillAnalyticEvent : HyperskillAnalyticEvent(HyperskillAnalyticRoute.Onboarding.Notifications, HyperskillAnalyticAction.VIEW) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponent.kt index 7d8afff9ad..04365756f7 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponent.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponent.kt @@ -2,9 +2,9 @@ package org.hyperskill.app.notifications_onboarding.injection import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Action import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Message -import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.State +import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.ViewState import ru.nobird.app.presentation.redux.feature.Feature interface NotificationsOnboardingComponent { - val notificationsOnboardingFeature: Feature + val notificationsOnboardingFeature: Feature } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponentImpl.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponentImpl.kt index a92cb3f96a..d5185a5d2d 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponentImpl.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingComponentImpl.kt @@ -3,16 +3,16 @@ package org.hyperskill.app.notifications_onboarding.injection import org.hyperskill.app.core.injection.AppGraph import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Action import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Message -import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.State +import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.ViewState import ru.nobird.app.presentation.redux.feature.Feature internal class NotificationsOnboardingComponentImpl( private val appGraph: AppGraph ) : NotificationsOnboardingComponent { - override val notificationsOnboardingFeature: Feature + override val notificationsOnboardingFeature: Feature get() = NotificationsOnboardingFeatureBuilder.build( - analyticInteractor = appGraph.analyticComponent.analyticInteractor, notificationInteractor = appGraph.buildNotificationComponent().notificationInteractor, + analyticInteractor = appGraph.analyticComponent.analyticInteractor, logger = appGraph.loggerComponent.logger, buildVariant = appGraph.commonComponent.buildKonfig.buildVariant ) diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingFeatureBuilder.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingFeatureBuilder.kt index 0ef512f50a..a7c044675d 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingFeatureBuilder.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/injection/NotificationsOnboardingFeatureBuilder.kt @@ -4,13 +4,16 @@ import co.touchlab.kermit.Logger import org.hyperskill.app.analytic.domain.interactor.AnalyticInteractor import org.hyperskill.app.core.domain.BuildVariant import org.hyperskill.app.core.presentation.ActionDispatcherOptions +import org.hyperskill.app.core.presentation.transformState import org.hyperskill.app.logging.presentation.wrapWithLogger import org.hyperskill.app.notification.local.domain.interactor.NotificationInteractor import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingActionDispatcher +import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Action import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Message -import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.State +import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.ViewState import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingReducer +import org.hyperskill.app.notifications_onboarding.view.mapper.NotificationsOnboardingViewStateMapper import ru.nobird.app.presentation.redux.dispatcher.wrapWithActionDispatcher import ru.nobird.app.presentation.redux.feature.Feature import ru.nobird.app.presentation.redux.feature.ReduxFeature @@ -19,17 +22,22 @@ internal object NotificationsOnboardingFeatureBuilder { private const val LOG_TAG = "NotificationsOnboardingFeature" fun build( - analyticInteractor: AnalyticInteractor, notificationInteractor: NotificationInteractor, + analyticInteractor: AnalyticInteractor, buildVariant: BuildVariant, logger: Logger - ): Feature { + ): Feature { val reducer = NotificationsOnboardingReducer().wrapWithLogger(buildVariant, logger, LOG_TAG) val actionDispatcher = NotificationsOnboardingActionDispatcher( config = ActionDispatcherOptions(), - analyticInteractor = analyticInteractor, - notificationInteractor = notificationInteractor + notificationInteractor = notificationInteractor, + analyticInteractor = analyticInteractor + ) + return ReduxFeature( + initialState = NotificationsOnboardingFeature.initialState(), + reducer = reducer ) - return ReduxFeature(State, reducer).wrapWithActionDispatcher(actionDispatcher) + .wrapWithActionDispatcher(actionDispatcher) + .transformState(NotificationsOnboardingViewStateMapper::mapState) } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingActionDispatcher.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingActionDispatcher.kt index 131add1162..04cd2768c0 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingActionDispatcher.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingActionDispatcher.kt @@ -16,10 +16,13 @@ internal class NotificationsOnboardingActionDispatcher( override suspend fun doSuspendableAction(action: Action) { when (action) { - InternalAction.UpdateLastNotificationPermissionRequestTime -> - notificationInteractor.updateLastTimeUserAskedToEnableDailyReminders() - is InternalAction.LogAnalyticEvent -> + is InternalAction.SaveDailyStudyRemindersIntervalStartHour -> { + notificationInteractor.setDailyStudyRemindersEnabled(enabled = true) + notificationInteractor.setDailyStudyReminderNotificationTime(notificationHour = action.startHour) + } + is InternalAction.LogAnalyticEvent -> { analyticInteractor.logEvent(action.analyticEvent) + } else -> { // no op } diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingFeature.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingFeature.kt index 961e51c938..7182d57197 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingFeature.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingFeature.kt @@ -1,26 +1,48 @@ package org.hyperskill.app.notifications_onboarding.presentation import org.hyperskill.app.analytic.domain.model.AnalyticEvent +import org.hyperskill.app.notification.local.cache.NotificationCacheKeyValues object NotificationsOnboardingFeature { - object State + internal data class State(val dailyStudyRemindersStartHour: Int) + + data class ViewState(val formattedDailyStudyRemindersInterval: String) + + internal fun initialState() = + State(dailyStudyRemindersStartHour = NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_START_HOUR_ONBOARDING) sealed interface Message { - object AllowNotificationClicked : Message - object RemindMeLaterClicked : Message + object AllowNotificationsClicked : Message + object NotNowClicked : Message data class NotificationPermissionRequestResult(val isPermissionGranted: Boolean) : Message + + object DailyStudyRemindsIntervalHourClicked : Message + data class DailyStudyRemindsIntervalStartHourSelected(val startHour: Int) : Message + + /** + * Analytic + */ object ViewedEventMessage : Message + + object DailyStudyRemindersIntervalStartHourPickerModalShownEventMessage : Message + object DailyStudyRemindersIntervalStartHourPickerModalHiddenEventMessage : Message } sealed interface Action { sealed interface ViewAction : Action { object RequestNotificationPermission : ViewAction object CompleteNotificationOnboarding : ViewAction + + data class ShowDailyStudyRemindersIntervalStartHourPickerModal( + val intervals: List, + val dailyStudyRemindersStartHour: Int + ) : ViewAction } } internal sealed interface InternalAction : Action { + data class SaveDailyStudyRemindersIntervalStartHour(val startHour: Int) : InternalAction + data class LogAnalyticEvent(val analyticEvent: AnalyticEvent) : InternalAction - object UpdateLastNotificationPermissionRequestTime : InternalAction } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingReducer.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingReducer.kt index 6523da21a0..c4626525d4 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingReducer.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/presentation/NotificationsOnboardingReducer.kt @@ -3,34 +3,44 @@ package org.hyperskill.app.notifications_onboarding.presentation import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute import org.hyperskill.app.notification.local.domain.analytic.NotificationSystemNoticeHiddenHyperskillAnalyticEvent import org.hyperskill.app.notification.local.domain.analytic.NotificationSystemNoticeShownHyperskillAnalyticEvent -import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent -import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingCompletionAppsFlyerAnalyticEvent -import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingViewedHyperskillAnalyticsEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent +import org.hyperskill.app.notifications_onboarding.domain.analytic.NotificationsOnboardingViewedHyperskillAnalyticEvent import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Action import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.InternalAction import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.Message import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature.State +import org.hyperskill.app.notifications_onboarding.view.mapper.NotificationsOnboardingViewStateMapper import ru.nobird.app.presentation.redux.reducer.StateReducer internal class NotificationsOnboardingReducer : StateReducer { override fun reduce(state: State, message: Message): Pair> = - state to when (message) { - Message.AllowNotificationClicked -> - setOf( + when (message) { + Message.AllowNotificationsClicked -> { + state to setOf( InternalAction.LogAnalyticEvent( - NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticsEvent + NotificationsOnboardingClickedAllowNotificationsHyperskillAnalyticEvent( + selectedDailyStudyRemindersStartHour = state.dailyStudyRemindersStartHour + ) ), InternalAction.LogAnalyticEvent( NotificationSystemNoticeShownHyperskillAnalyticEvent( HyperskillAnalyticRoute.Onboarding.Notifications ) ), - InternalAction.UpdateLastNotificationPermissionRequestTime, + InternalAction.SaveDailyStudyRemindersIntervalStartHour( + startHour = state.dailyStudyRemindersStartHour + ), Action.ViewAction.RequestNotificationPermission ) - is Message.NotificationPermissionRequestResult -> - setOf( + } + is Message.NotificationPermissionRequestResult -> { + state to setOf( InternalAction.LogAnalyticEvent( NotificationSystemNoticeHiddenHyperskillAnalyticEvent( route = HyperskillAnalyticRoute.Onboarding.Notifications, @@ -44,18 +54,58 @@ internal class NotificationsOnboardingReducer : StateReducer - setOf( + } + Message.NotNowClicked -> { + state to setOf( InternalAction.LogAnalyticEvent( - NotificationsOnboardingClickedRemindMeLaterHyperskillAnalyticsEvent + NotificationsOnboardingClickedNotNowHyperskillAnalyticEvent ), InternalAction.LogAnalyticEvent( NotificationsOnboardingCompletionAppsFlyerAnalyticEvent(isSuccess = false) ), - InternalAction.UpdateLastNotificationPermissionRequestTime, Action.ViewAction.CompleteNotificationOnboarding ) - Message.ViewedEventMessage -> - setOf(InternalAction.LogAnalyticEvent(NotificationsOnboardingViewedHyperskillAnalyticsEvent)) + } + Message.DailyStudyRemindsIntervalHourClicked -> { + state to setOf( + InternalAction.LogAnalyticEvent( + NotificationsOnboardingClickedDailyStudyRemindsIntervalHourHyperskillAnalyticEvent( + currentDailyStudyRemindersStartHour = state.dailyStudyRemindersStartHour + ) + ), + Action.ViewAction.ShowDailyStudyRemindersIntervalStartHourPickerModal( + intervals = (0..23).map { hour -> + NotificationsOnboardingViewStateMapper.formatDailyStudyRemindersInterval(startHour = hour) + }, + dailyStudyRemindersStartHour = state.dailyStudyRemindersStartHour + ) + ) + } + is Message.DailyStudyRemindsIntervalStartHourSelected -> { + val analyticEvent = + NotificationsOnboardingDailyStudyRemindersIntervalPickerModalClickedConfirmHyperskillAnalyticEvent( + selectedDailyStudyRemindersStartHour = message.startHour + ) + state.copy( + dailyStudyRemindersStartHour = message.startHour + ) to setOf(InternalAction.LogAnalyticEvent(analyticEvent)) + } + Message.DailyStudyRemindersIntervalStartHourPickerModalHiddenEventMessage -> { + state to setOf( + InternalAction.LogAnalyticEvent( + NotificationsOnboardingDailyStudyRemindersIntervalPickerModalHiddenHyperskillAnalyticEvent + ) + ) + } + Message.DailyStudyRemindersIntervalStartHourPickerModalShownEventMessage -> { + state to setOf( + InternalAction.LogAnalyticEvent( + NotificationsOnboardingDailyStudyRemindersIntervalPickerModalShownHyperskillAnalyticEvent + ) + ) + } + Message.ViewedEventMessage -> { + state to setOf(InternalAction.LogAnalyticEvent(NotificationsOnboardingViewedHyperskillAnalyticEvent)) + } } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/view/mapper/NotificationsOnboardingViewStateMapper.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/view/mapper/NotificationsOnboardingViewStateMapper.kt new file mode 100644 index 0000000000..409a1bdea9 --- /dev/null +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/notifications_onboarding/view/mapper/NotificationsOnboardingViewStateMapper.kt @@ -0,0 +1,24 @@ +package org.hyperskill.app.notifications_onboarding.view.mapper + +import org.hyperskill.app.notifications_onboarding.presentation.NotificationsOnboardingFeature + +internal object NotificationsOnboardingViewStateMapper { + fun mapState(state: NotificationsOnboardingFeature.State): NotificationsOnboardingFeature.ViewState = + NotificationsOnboardingFeature.ViewState( + formattedDailyStudyRemindersInterval = formatDailyStudyRemindersInterval( + startHour = state.dailyStudyRemindersStartHour + ) + ) + + fun formatDailyStudyRemindersInterval(startHour: Int): String { + val endHour = startHour + 1 + return buildString { + append(if (startHour < 10) "0" else "") + append(startHour) + append(":00 - ") + append(if (endHour < 10) "0" else "") + append(endHour) + append(":00") + } + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent.kt deleted file mode 100644 index dc27825165..0000000000 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent.kt +++ /dev/null @@ -1,31 +0,0 @@ -package org.hyperskill.app.step_completion.domain.analytic - -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget - -/** - * Represents a hidden analytic event of the prompt to receive daily study reminders. - * - * JSON payload: - * ``` - * { - * "route": "/learn/step/1", - * "action": "hidden", - * "part": "daily_notifications_notice", - * "target": "ok / later" - * } - * ``` - * @see HyperskillAnalyticEvent - */ -class StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent( - route: HyperskillAnalyticRoute, - isAgreed: Boolean -) : HyperskillAnalyticEvent( - route, - HyperskillAnalyticAction.HIDDEN, - HyperskillAnalyticPart.DAILY_NOTIFICATIONS_NOTICE, - target = if (isAgreed) HyperskillAnalyticTarget.OK else HyperskillAnalyticTarget.LATER -) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent.kt deleted file mode 100644 index a7d9d1b736..0000000000 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/domain/analytic/StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.hyperskill.app.step_completion.domain.analytic - -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticAction -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticEvent -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticPart -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticRoute -import org.hyperskill.app.analytic.domain.model.hyperskill.HyperskillAnalyticTarget - -/** - * Represents a shown analytic event of the prompt to receive daily study reminders. - * - * JSON payload: - * ``` - * { - * "route": "/learn/step/1", - * "action": "hidden", - * "part": "notice", - * "target": "daily_notifications_notice" - * } - * ``` - * @see HyperskillAnalyticEvent - */ -class StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent( - route: HyperskillAnalyticRoute, -) : HyperskillAnalyticEvent( - route, - HyperskillAnalyticAction.SHOWN, - HyperskillAnalyticPart.NOTICE, - HyperskillAnalyticTarget.DAILY_NOTIFICATIONS_NOTICE -) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/injection/StepCompletionComponentImpl.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/injection/StepCompletionComponentImpl.kt index 74b08c63a7..6b6446597f 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/injection/StepCompletionComponentImpl.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/injection/StepCompletionComponentImpl.kt @@ -30,7 +30,6 @@ internal class StepCompletionComponentImpl( appGraph.stateRepositoriesComponent.currentGamificationToolbarDataStateRepository, appGraph.stepCompletionFlowDataComponent.dailyStepCompletedFlow, appGraph.stepCompletionFlowDataComponent.topicCompletedFlow, - appGraph.progressesFlowDataComponent.topicProgressFlow, - appGraph.buildNotificationComponent().notificationInteractor + appGraph.progressesFlowDataComponent.topicProgressFlow ) } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionActionDispatcher.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionActionDispatcher.kt index 7458abb811..38e76f8ccd 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionActionDispatcher.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionActionDispatcher.kt @@ -11,8 +11,6 @@ import org.hyperskill.app.core.view.mapper.ResourceProvider import org.hyperskill.app.freemium.domain.interactor.FreemiumInteractor import org.hyperskill.app.gamification_toolbar.domain.repository.CurrentGamificationToolbarDataStateRepository import org.hyperskill.app.learning_activities.domain.repository.NextLearningActivityStateRepository -import org.hyperskill.app.notification.local.cache.NotificationCacheKeyValues -import org.hyperskill.app.notification.local.domain.interactor.NotificationInteractor import org.hyperskill.app.profile.domain.repository.CurrentProfileStateRepository import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow import org.hyperskill.app.progresses.domain.interactor.ProgressesInteractor @@ -49,8 +47,7 @@ class StepCompletionActionDispatcher( private val currentGamificationToolbarDataStateRepository: CurrentGamificationToolbarDataStateRepository, private val dailyStepCompletedFlow: DailyStepCompletedFlow, private val topicCompletedFlow: TopicCompletedFlow, - private val topicProgressFlow: TopicProgressFlow, - private val notificationInteractor: NotificationInteractor + private val topicProgressFlow: TopicProgressFlow ) : CoroutineActionDispatcher(config.createConfig()) { init { @@ -97,12 +94,6 @@ class StepCompletionActionDispatcher( is Action.UpdateProblemsLimit -> { freemiumInteractor.onStepSolved() } - is Action.TurnOnDailyStudyReminder -> { - handleTurnOnDailyStudyReminderAction() - } - is Action.PostponeDailyStudyReminder -> { - handlePostponeDailyStudyReminderAction() - } is Action.UpdateLastTimeShareStreakShown -> { shareStreakInteractor.setLastTimeShareStreakShown() } @@ -186,17 +177,6 @@ class StepCompletionActionDispatcher( } } - private suspend fun handleTurnOnDailyStudyReminderAction() { - notificationInteractor.setDailyStudyRemindersEnabled(true) - notificationInteractor.setDailyStudyReminderNotificationTime( - NotificationCacheKeyValues.DAILY_STUDY_REMINDERS_START_HOUR_AFTER_STEP_SOLVED - ) - } - - private fun handlePostponeDailyStudyReminderAction() { - notificationInteractor.updateLastTimeUserAskedToEnableDailyReminders() - } - private suspend fun handleStepSolved(stepId: Long) { // update problems limit onNewMessage(Message.StepSolved(stepId)) @@ -237,13 +217,6 @@ class StepCompletionActionDispatcher( false } - // TODO: ALTUX-2415 Enhance the user experience of "Daily Study Reminders" - if (notificationInteractor.isRequiredToAskUserToEnableDailyReminders()) { - onNewMessage(Message.RequestDailyStudyRemindersPermission) - updateCurrentProfileHypercoinsBalanceRemotely() - return - } - if (cachedProfile.dailyStep == stepId) { val currentProfileHypercoinsBalance = updateCurrentProfileHypercoinsBalanceRemotely() if (currentProfileHypercoinsBalance != null) { diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionFeature.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionFeature.kt index e11e3dc431..0a85456f78 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionFeature.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionFeature.kt @@ -101,12 +101,6 @@ interface StepCompletionFeature { object ProblemOfDaySolvedModalGoBackClicked : Message data class ProblemOfDaySolvedModalShareStreakClicked(val streak: Int) : Message - /** - * Daily study reminders - */ - object RequestDailyStudyRemindersPermission : Message - data class RequestDailyStudyRemindersPermissionResult(val isGranted: Boolean) : Message - /** * Share streak */ @@ -135,9 +129,6 @@ interface StepCompletionFeature { object UpdateProblemsLimit : Action - object TurnOnDailyStudyReminder : Action - object PostponeDailyStudyReminder : Action - object UpdateLastTimeShareStreakShown : Action sealed interface ViewAction : Action { @@ -154,8 +145,6 @@ interface StepCompletionFeature { data class ShowShareStreakModal(val streak: Int) : ViewAction data class ShowShareStreakSystemModal(val streak: Int) : ViewAction - object RequestDailyStudyRemindersPermission : ViewAction - data class ShowStartPracticingError(val message: String) : ViewAction data class ReloadStep(val stepRoute: StepRoute) : ViewAction diff --git a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionReducer.kt b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionReducer.kt index 903fab45d7..3006961a5d 100644 --- a/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionReducer.kt +++ b/shared/src/commonMain/kotlin/org/hyperskill/app/step_completion/presentation/StepCompletionReducer.kt @@ -10,12 +10,10 @@ import org.hyperskill.app.step_completion.domain.analytic.StepCompletionDailySte import org.hyperskill.app.step_completion.domain.analytic.StepCompletionDailyStepCompletedModalClickedShareStreakHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionDailyStepCompletedModalHiddenHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionDailyStepCompletedModalShownHyperskillAnalyticEvent -import org.hyperskill.app.step_completion.domain.analytic.StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionShareStreakModalClickedNoThanksHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionShareStreakModalClickedShareHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionShareStreakModalHiddenHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionShareStreakModalShownHyperskillAnalyticEvent -import org.hyperskill.app.step_completion.domain.analytic.StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionTopicCompletedModalClickedContinueNextTopicHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionTopicCompletedModalClickedGoToStudyPlanHyperskillAnalyticEvent import org.hyperskill.app.step_completion.domain.analytic.StepCompletionTopicCompletedModalHiddenHyperskillAnalyticEvent @@ -158,28 +156,6 @@ class StepCompletionReducer(private val stepRoute: StepRoute) : StateReducer { - state to setOfNotNull( - Action.ViewAction.RequestDailyStudyRemindersPermission, - Action.LogAnalyticEvent( - StepCompletionShownDailyNotificationsNoticeHyperskillAnalyticEvent(stepRoute.analyticRoute) - ) - ) - } - is Message.RequestDailyStudyRemindersPermissionResult -> { - val analyticEvent = StepCompletionHiddenDailyNotificationsNoticeHyperskillAnalyticEvent( - route = stepRoute.analyticRoute, - isAgreed = message.isGranted - ) - state to setOf( - if (message.isGranted) { - Action.TurnOnDailyStudyReminder - } else { - Action.PostponeDailyStudyReminder - }, - Action.LogAnalyticEvent(analyticEvent) - ) - } is Message.ShareStreak -> { state to setOf(Action.ViewAction.ShowShareStreakModal(streak = message.streak)) } diff --git a/shared/src/commonMain/resources/MR/base/strings.xml b/shared/src/commonMain/resources/MR/base/strings.xml index 520c1276d1..5ec873b24d 100644 --- a/shared/src/commonMain/resources/MR/base/strings.xml +++ b/shared/src/commonMain/resources/MR/base/strings.xml @@ -398,12 +398,17 @@ Sign up + Track your progress + Choose a time for your daily practice and we\'ll remind you to + stay on track + Enable notifications to keep your streak alive and stay consistently on top of your learning + Set time Allow notifications - Remind me later + Not now Let\'s keep going! @@ -414,10 +419,6 @@ Start learning Failed to load first problem - - Stay motivated with daily reminders - The app will send you notifications to practice everyday and keep up your learning streak - Learn next