diff --git a/app/src/extra/java/org/wikipedia/donate/GooglePayActivity.kt b/app/src/extra/java/org/wikipedia/donate/GooglePayActivity.kt index cf38dd1aa5b..055ee2b5871 100644 --- a/app/src/extra/java/org/wikipedia/donate/GooglePayActivity.kt +++ b/app/src/extra/java/org/wikipedia/donate/GooglePayActivity.kt @@ -278,6 +278,7 @@ class GooglePayActivity : BaseActivity() { } binding.amountPresetsFlow.referencedIds = viewIds.toIntArray() setFilledAmountToText() + setCheckedRecurringDonation() setButtonHighlighted(filledAmountButton) } @@ -287,6 +288,10 @@ class GooglePayActivity : BaseActivity() { } } + private fun setCheckedRecurringDonation() { + binding.checkBoxRecurring.isChecked = viewModel.checkedRecurringDonation + } + private fun setButtonHighlighted(button: View? = null) { binding.amountPresetsContainer.children.forEach { child -> if (child is MaterialButton) { @@ -315,12 +320,14 @@ class GooglePayActivity : BaseActivity() { companion object { private const val CAMPAIGN_ID_APP_MENU = "appmenu" const val FILLED_AMOUNT = "filledAmount" + const val CHECKED_RECURRING_DONATION = "checkedRecurringDonation" - fun newIntent(context: Context, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f): Intent { + fun newIntent(context: Context, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f, checkedRecurringDonation: Boolean = false): Intent { return Intent(context, GooglePayActivity::class.java) .putExtra(DonateDialog.ARG_CAMPAIGN_ID, campaignId) .putExtra(DonateDialog.ARG_DONATE_URL, donateUrl) .putExtra(FILLED_AMOUNT, filledAmount) + .putExtra(CHECKED_RECURRING_DONATION, checkedRecurringDonation) } } } diff --git a/app/src/extra/java/org/wikipedia/donate/GooglePayComponent.kt b/app/src/extra/java/org/wikipedia/donate/GooglePayComponent.kt index 8a2229da2b3..75ec9741cde 100644 --- a/app/src/extra/java/org/wikipedia/donate/GooglePayComponent.kt +++ b/app/src/extra/java/org/wikipedia/donate/GooglePayComponent.kt @@ -78,8 +78,8 @@ internal object GooglePayComponent { return available } - fun getDonateActivityIntent(activity: Activity, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f): Intent { - return GooglePayActivity.newIntent(activity, campaignId, donateUrl, filledAmount) + fun getDonateActivityIntent(activity: Activity, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f, checkedRecurringDonation: Boolean = false): Intent { + return GooglePayActivity.newIntent(activity, campaignId, donateUrl, filledAmount, checkedRecurringDonation) } fun getPaymentDataRequestJson( diff --git a/app/src/extra/java/org/wikipedia/donate/GooglePayViewModel.kt b/app/src/extra/java/org/wikipedia/donate/GooglePayViewModel.kt index 07927a8065f..34d3b067c3d 100644 --- a/app/src/extra/java/org/wikipedia/donate/GooglePayViewModel.kt +++ b/app/src/extra/java/org/wikipedia/donate/GooglePayViewModel.kt @@ -32,6 +32,7 @@ import kotlin.math.abs class GooglePayViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { val filledAmount = savedStateHandle.get(GooglePayActivity.FILLED_AMOUNT) ?: 0f + val checkedRecurringDonation = savedStateHandle.get(GooglePayActivity.CHECKED_RECURRING_DONATION) ?: false val uiState = MutableStateFlow(Resource()) private var donationConfig: DonationConfig? = null diff --git a/app/src/fdroid/java/org/wikipedia/donate/GooglePayComponent.kt b/app/src/fdroid/java/org/wikipedia/donate/GooglePayComponent.kt index 16d2a28b8a1..a126fa92cf4 100644 --- a/app/src/fdroid/java/org/wikipedia/donate/GooglePayComponent.kt +++ b/app/src/fdroid/java/org/wikipedia/donate/GooglePayComponent.kt @@ -10,7 +10,7 @@ object GooglePayComponent { return false } - fun getDonateActivityIntent(activity: Activity, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f): Intent { + fun getDonateActivityIntent(activity: Activity, campaignId: String? = null, donateUrl: String? = null, filledAmount: Float = 0f, checkedRecurringDonation: Boolean = false): Intent { return Intent() } } diff --git a/app/src/main/java/org/wikipedia/donate/DonateDialog.kt b/app/src/main/java/org/wikipedia/donate/DonateDialog.kt index 08b4f525fc7..4a126280403 100644 --- a/app/src/main/java/org/wikipedia/donate/DonateDialog.kt +++ b/app/src/main/java/org/wikipedia/donate/DonateDialog.kt @@ -22,6 +22,7 @@ import org.wikipedia.donate.donationreminder.DonationReminderHelper import org.wikipedia.page.ExtendedBottomSheetDialogFragment import org.wikipedia.settings.Prefs import org.wikipedia.util.CustomTabsUtil +import org.wikipedia.util.DimenUtil import org.wikipedia.util.FeedbackUtil import org.wikipedia.util.Resource @@ -87,7 +88,7 @@ class DonateDialog : ExtendedBottomSheetDialogFragment() { } } if (arguments?.getBoolean(ARG_FROM_DONATION_REMINDER) == true) { - setupDirectGooglePayButton() + setupDirectGooglePayButton(arguments?.getBoolean(ARG_FROM_DONATION_REMINDER_WRAP_UP) ?: false) } } } @@ -114,10 +115,14 @@ class DonateDialog : ExtendedBottomSheetDialogFragment() { } } - private fun setupDirectGooglePayButton() { - val donateAmount = Prefs.donationReminderConfig.donateAmount + private fun setupDirectGooglePayButton(fromDonationReminderWrapUp: Boolean) { + val donateAmount = if (Prefs.donationReminderConfig.donateAmount <= 0) { + DonationReminderHelper.defaultDonateAmountOptions.first() + } else { + Prefs.donationReminderConfig.donateAmount + } val donateAmountText = - DonateUtil.currencyFormat.format(Prefs.donationReminderConfig.donateAmount) + DonateUtil.currencyFormat.format(donateAmount) val donateButtonText = getString(R.string.donation_reminders_gpay_text, donateAmountText) binding.donateGooglePayButton.text = donateButtonText binding.donateGooglePayButton.setOnClickListener { @@ -127,7 +132,13 @@ class DonateDialog : ExtendedBottomSheetDialogFragment() { campaignId = DonationReminderHelper.getCampaignId() ) (requireActivity() as? BaseActivity)?.launchDonateActivity( - GooglePayComponent.getDonateActivityIntent(requireActivity(), filledAmount = donateAmount, campaignId = DonationReminderHelper.getCampaignId())) + GooglePayComponent.getDonateActivityIntent( + activity = requireActivity(), + filledAmount = donateAmount, + checkedRecurringDonation = fromDonationReminderWrapUp, + campaignId = DonationReminderHelper.getCampaignId() + ) + ) } binding.donateGooglePayDifferentAmountButton.isVisible = true binding.donateGooglePayDifferentAmountButton.setOnClickListener { @@ -137,7 +148,12 @@ class DonateDialog : ExtendedBottomSheetDialogFragment() { campaignId = DonationReminderHelper.getCampaignId() ) (requireActivity() as? BaseActivity)?.launchDonateActivity( - GooglePayComponent.getDonateActivityIntent(requireActivity(), campaignId = DonationReminderHelper.getCampaignId())) + GooglePayComponent.getDonateActivityIntent( + activity = requireActivity(), + campaignId = DonationReminderHelper.getCampaignId(), + checkedRecurringDonation = fromDonationReminderWrapUp + ) + ) } binding.donateOtherButton.setOnClickListener { DonorExperienceEvent.logDonationReminderAction( @@ -147,21 +163,38 @@ class DonateDialog : ExtendedBottomSheetDialogFragment() { ) onDonateClicked() } - binding.gPayHeaderContainer.isVisible = false + if (fromDonationReminderWrapUp) { + binding.gPayTitle.text = getString(R.string.donation_reminders_eoe_donate_dialog_title) + (binding.gPayTitle.layoutParams as? ViewGroup.MarginLayoutParams)?.let { params -> + params.bottomMargin = DimenUtil.roundedDpToPx(16.0f) + binding.gPayTitle.layoutParams = params + } + binding.gPayDescription.isVisible = false + } else { + binding.gPayHeaderContainer.isVisible = false + } } companion object { const val ARG_CAMPAIGN_ID = "campaignId" const val ARG_DONATE_URL = "donateUrl" const val ARG_FROM_DONATION_REMINDER = "fromDonationReminder" + const val ARG_FROM_DONATION_REMINDER_WRAP_UP = "fromDonationReminderWrapUp" const val ARG_FROM_YIR = "fromYiR" - fun newInstance(campaignId: String? = null, donateUrl: String? = null, fromDonationReminder: Boolean = false, fromYiR: Boolean = false): DonateDialog { + fun newInstance( + campaignId: String? = null, + donateUrl: String? = null, + fromDonationReminder: Boolean = false, + fromYiR: Boolean = false, + fromDonationReminderWrapUp: Boolean = false + ): DonateDialog { return DonateDialog().apply { arguments = Bundle().apply { putString(ARG_CAMPAIGN_ID, campaignId) putString(ARG_DONATE_URL, donateUrl) putBoolean(ARG_FROM_DONATION_REMINDER, fromDonationReminder) + putBoolean(ARG_FROM_DONATION_REMINDER_WRAP_UP, fromDonationReminderWrapUp) putBoolean(ARG_FROM_YIR, fromYiR) } } diff --git a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderActivity.kt b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderActivity.kt index 5c7b4cecf3c..8f2f5677fff 100644 --- a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderActivity.kt +++ b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderActivity.kt @@ -12,6 +12,7 @@ import org.wikipedia.analytics.eventplatform.DonorExperienceEvent import org.wikipedia.compose.components.error.WikiErrorClickEvents import org.wikipedia.compose.theme.BaseTheme import org.wikipedia.readinglist.recommended.RecommendedReadingListOnboardingActivity.Companion.EXTRA_FROM_SETTINGS +import org.wikipedia.settings.Prefs import org.wikipedia.util.DeviceUtil import org.wikipedia.util.FeedbackUtil import org.wikipedia.util.UriUtil @@ -74,6 +75,7 @@ class DonationReminderActivity : BaseActivity() { } } sendAnalysis() + enableWrapUp() } private fun sendAnalysis() { @@ -86,6 +88,14 @@ class DonationReminderActivity : BaseActivity() { } } + private fun enableWrapUp() { + if (!DonationReminderHelper.isWrapUpEnabled) { + Prefs.donationReminderConfig = Prefs.donationReminderConfig.copy( + wrapUpEnabled = true + ) + } + } + companion object { const val RESULT_OK_FROM_DONATION_REMINDER = 100 fun newIntent(context: Context, isFromSettings: Boolean = false): Intent { diff --git a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderCardView.kt b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderCardView.kt index cffbdd40f54..b6a5e13c465 100644 --- a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderCardView.kt +++ b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderCardView.kt @@ -3,8 +3,13 @@ package org.wikipedia.donate.donationreminder import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater +import androidx.core.net.toUri +import androidx.core.view.isVisible +import org.wikipedia.R import org.wikipedia.databinding.ViewDonationReminderCardBinding import org.wikipedia.util.DimenUtil +import org.wikipedia.util.StringUtil +import org.wikipedia.util.UriUtil import org.wikipedia.views.WikiCardView class DonationReminderCardView(context: Context, attrs: AttributeSet? = null) : WikiCardView(context, attrs) { @@ -21,7 +26,7 @@ class DonationReminderCardView(context: Context, attrs: AttributeSet? = null) : } fun setMessage(text: String) { - binding.messageTextView.text = text + binding.messageTextView.text = StringUtil.fromHtml(text) } fun setPositiveButton(text: String, listener: OnClickListener) { @@ -33,4 +38,15 @@ class DonationReminderCardView(context: Context, attrs: AttributeSet? = null) : binding.negativeButton.text = text binding.negativeButton.setOnClickListener(listener) } + + fun showWrapUpContainer() { + binding.wrapUpContainer.isVisible = true + binding.learnMoreButton.setOnClickListener { + UriUtil.visitInExternalBrowser(context, context.getString(R.string.donation_reminders_experiment_url).toUri()) + } + } +} + +enum class DonationReminderType { + GENERAL, WRAP_UP } diff --git a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderHelper.kt b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderHelper.kt index 23f15881fc5..e2f9f996a6d 100644 --- a/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderHelper.kt +++ b/app/src/main/java/org/wikipedia/donate/donationreminder/DonationReminderHelper.kt @@ -22,7 +22,9 @@ object DonationReminderHelper { private val enabledCountries = listOf( "NL" ) - private val isInDateRange get() = LocalDate.now() <= LocalDate.of(2026, 11, 9) // TODO: confirm with PM + private val isInDateRange get() = LocalDate.now() <= LocalDate.of(2026, 11, 9) + private val isInWrapUpDateRange get() = LocalDate.now() <= LocalDate.of(2026, 11, 15) && + LocalDate.now() >= LocalDate.of(2026, 11, 10) val isInEligibleCountry get() = ReleaseUtil.isDevRelease || enabledCountries.contains(GeoUtil.geoIPCountry.orEmpty()) val defaultReadFrequencyOptions = listOf(5, 10, 20) val presetsToRemoveFromConfig = listOf(2f, 10f, 15f) // V3 only. @@ -30,18 +32,21 @@ object DonationReminderHelper { val isEnabled get() = (ReleaseUtil.isDevRelease || isInEligibleCountry && isInDateRange) && isTestGroupUser + val isWrapUpEnabled + get() = (Prefs.donationReminderDevWrapUp && Prefs.donationReminderConfig.wrapUpEnabled || isInEligibleCountry && isInWrapUpDateRange) && + isTestGroupUser && Prefs.donationReminderConfig.wrapUpEnabled val hasActiveReminder get() = Prefs.donationReminderConfig.userEnabled && Prefs.donationReminderConfig.isReminderReady && isInEligibleCountry var shouldShowSettingSnackbar = false fun getCampaignId(campaignIdOriginal: String = "appmenu"): String { - return if (isInEligibleCountry && isInDateRange) { + return if (isInEligibleCountry && (isInDateRange || isInWrapUpDateRange)) { campaignIdOriginal + when (DonationReminderAbTest().group) { GROUP_3 -> "_reminderC" GROUP_2 -> "_reminderB" else -> "_reminderA" - } // TODO: confirm with Shay + } } else { campaignIdOriginal } @@ -114,9 +119,16 @@ object DonationReminderHelper { fun dismissReminder() { val config = Prefs.donationReminderConfig - Prefs.donationReminderConfig = config.copy( - isReminderReady = false - ) + if (isWrapUpEnabled) { + Prefs.donationReminderConfig = config.copy( + wrapUpEnabled = false + ) + Prefs.donationReminderDevWrapUp = false + } else { + Prefs.donationReminderConfig = config.copy( + isReminderReady = false + ) + } } } @@ -130,7 +142,8 @@ data class DonationReminderConfig( val donateAmount: Float = 0f, val isReminderReady: Boolean = false, val timesReminderShown: Int = 0, - val goalReachedCount: Int = 0 + val goalReachedCount: Int = 0, + val wrapUpEnabled: Boolean = false ) { val isSetup: Boolean get() = userEnabled && setupTimestamp != 0L && articleFrequency > 0 diff --git a/app/src/main/java/org/wikipedia/page/campaign/CampaignDialog.kt b/app/src/main/java/org/wikipedia/page/campaign/CampaignDialog.kt index 4fc1cbf5a7e..f64f186746c 100644 --- a/app/src/main/java/org/wikipedia/page/campaign/CampaignDialog.kt +++ b/app/src/main/java/org/wikipedia/page/campaign/CampaignDialog.kt @@ -87,6 +87,10 @@ class CampaignDialog internal constructor(private val context: Context, val camp campaignId = campaignId ) DonationReminderAbTest().maybeSendExposureEvent() + // Enable wrap up for the user if they are in the eligible country and have seen the campaign. + Prefs.donationReminderConfig = Prefs.donationReminderConfig.copy( + wrapUpEnabled = true + ) } if (!DonationReminderHelper.isEnabled) { Prefs.announcementPauseTime = Date().time diff --git a/app/src/main/java/org/wikipedia/page/leadimages/LeadImagesHandler.kt b/app/src/main/java/org/wikipedia/page/leadimages/LeadImagesHandler.kt index bbaf963da2d..90d8c7b85dd 100644 --- a/app/src/main/java/org/wikipedia/page/leadimages/LeadImagesHandler.kt +++ b/app/src/main/java/org/wikipedia/page/leadimages/LeadImagesHandler.kt @@ -13,6 +13,7 @@ import org.wikipedia.Constants.ImageEditType import org.wikipedia.Constants.InvokeSource import org.wikipedia.R import org.wikipedia.WikipediaApp +import org.wikipedia.analytics.ABTest.Companion.GROUP_2 import org.wikipedia.analytics.eventplatform.DonorExperienceEvent import org.wikipedia.auth.AccountUtil import org.wikipedia.bridge.JavaScriptActionHandler @@ -23,8 +24,10 @@ import org.wikipedia.dataclient.WikiSite import org.wikipedia.dataclient.mwapi.MwQueryPage import org.wikipedia.descriptions.DescriptionEditActivity import org.wikipedia.donate.DonateDialog +import org.wikipedia.donate.donationreminder.DonationReminderAbTest import org.wikipedia.donate.donationreminder.DonationReminderActivity import org.wikipedia.donate.donationreminder.DonationReminderHelper +import org.wikipedia.donate.donationreminder.DonationReminderType import org.wikipedia.gallery.GalleryActivity import org.wikipedia.page.ExclusiveBottomSheetPresenter import org.wikipedia.page.PageFragment @@ -36,6 +39,7 @@ import org.wikipedia.util.FeedbackUtil import org.wikipedia.util.StringUtil import org.wikipedia.util.log.L import org.wikipedia.views.ObservableWebView +import org.wikipedia.views.SurveyDialog class LeadImagesHandler(private val parentFragment: PageFragment, webView: ObservableWebView, @@ -206,30 +210,52 @@ class LeadImagesHandler(private val parentFragment: PageFragment, } } - override fun donationReminderCardPositiveClicked() { + override fun donationReminderCardPositiveClicked(type: DonationReminderType) { hideDonationReminderCard() - DonorExperienceEvent.logDonationReminderAction( - activeInterface = "reminder_milestone", - action = "donate_start_click", - campaignId = DonationReminderHelper.getCampaignId() - ) - ExclusiveBottomSheetPresenter.show(parentFragment.parentFragmentManager, DonateDialog.newInstance(fromDonationReminder = true)) + if (type == DonationReminderType.WRAP_UP) { + if (DonationReminderAbTest().group == GROUP_2) { + SurveyDialog.showDonationReminderFeedbackDialog( + activity = parentFragment.requireActivity(), + onImpression = { + // TODO: instrumentation + }, + onCancel = { + // TODO: instrumentation + }, + onSubmit = { feedbackOption, feedbackText -> + // TODO: instrumentation + } + ) + } else { + ExclusiveBottomSheetPresenter.show(parentFragment.parentFragmentManager, DonateDialog.newInstance(fromDonationReminder = true, fromDonationReminderWrapUp = true)) + } + } else { + DonorExperienceEvent.logDonationReminderAction( + activeInterface = "reminder_milestone", + action = "donate_start_click", + campaignId = DonationReminderHelper.getCampaignId() + ) + ExclusiveBottomSheetPresenter.show(parentFragment.parentFragmentManager, DonateDialog.newInstance(fromDonationReminder = true)) + } } - override fun donationReminderCardNegativeClicked() { + override fun donationReminderCardNegativeClicked(type: DonationReminderType) { hideDonationReminderCard() - DonorExperienceEvent.logDonationReminderAction( - activeInterface = "reminder_milestone", - action = "notnow_click" - ) - FeedbackUtil.makeSnackbar(activity, activity.getString(R.string.donation_reminders_prompt_dismiss_snackbar)) - .setAction(R.string.donation_reminders_snackbar_modify_button_label) { - DonorExperienceEvent.logDonationReminderAction( - activeInterface = "reminder_milestone", - action = "setting_click" - ) - activity.startActivity(DonationReminderActivity.newIntent(activity, isFromSettings = true)) - }.show() + if (type == DonationReminderType.WRAP_UP) { + // TODO: instrumentation + } else { + DonorExperienceEvent.logDonationReminderAction( + activeInterface = "reminder_milestone", + action = "notnow_click" + ) + FeedbackUtil.makeSnackbar(activity, activity.getString(R.string.donation_reminders_prompt_dismiss_snackbar)) + .setAction(R.string.donation_reminders_snackbar_modify_button_label) { + DonorExperienceEvent.logDonationReminderAction(activeInterface = "reminder_milestone", + action = "setting_click" + ) + activity.startActivity(DonationReminderActivity.newIntent(activity, isFromSettings = true)) + }.show() + } } } } diff --git a/app/src/main/java/org/wikipedia/page/leadimages/PageHeaderView.kt b/app/src/main/java/org/wikipedia/page/leadimages/PageHeaderView.kt index 1350f06cd7b..df235ee792e 100644 --- a/app/src/main/java/org/wikipedia/page/leadimages/PageHeaderView.kt +++ b/app/src/main/java/org/wikipedia/page/leadimages/PageHeaderView.kt @@ -9,11 +9,14 @@ import androidx.core.net.toUri import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import org.wikipedia.R +import org.wikipedia.analytics.ABTest.Companion.GROUP_2 import org.wikipedia.analytics.eventplatform.DonorExperienceEvent import org.wikipedia.databinding.ViewPageHeaderBinding import org.wikipedia.donate.DonateUtil +import org.wikipedia.donate.donationreminder.DonationReminderAbTest import org.wikipedia.donate.donationreminder.DonationReminderConfig import org.wikipedia.donate.donationreminder.DonationReminderHelper +import org.wikipedia.donate.donationreminder.DonationReminderType import org.wikipedia.settings.Prefs import org.wikipedia.util.DateUtil import org.wikipedia.util.DimenUtil @@ -27,8 +30,8 @@ class PageHeaderView(context: Context, attrs: AttributeSet? = null) : LinearLayo interface Callback { fun onImageClicked() fun onCallToActionClicked() - fun donationReminderCardPositiveClicked() - fun donationReminderCardNegativeClicked() + fun donationReminderCardPositiveClicked(type: DonationReminderType) + fun donationReminderCardNegativeClicked(type: DonationReminderType) } private val binding = ViewPageHeaderBinding.inflate(LayoutInflater.from(context), this) @@ -139,40 +142,80 @@ class PageHeaderView(context: Context, attrs: AttributeSet? = null) : LinearLayo private fun updateDonationReminderCardContent(config: DonationReminderConfig?) { config?.let { config -> + val isWrapUpEnabled = DonationReminderHelper.isWrapUpEnabled + val reminderCardType = if (isWrapUpEnabled) DonationReminderType.WRAP_UP else DonationReminderType.GENERAL val articleText = context.resources.getQuantityString( R.plurals.donation_reminders_text_articles, config.articleFrequency, config.articleFrequency ) - val donationAmount = DonateUtil.currencyFormat.format(Prefs.donationReminderConfig.donateAmount) - val titleText = if (config.goalReachedCount == 1) { - context.getString(R.string.donation_reminders_first_milestone_reached_prompt_title, articleText, donationAmount) + val donateAmount = if (Prefs.donationReminderConfig.donateAmount <= 0) { + DonationReminderHelper.defaultDonateAmountOptions.first() } else { - context.getString(R.string.donation_reminders_subsequent_milestone_reached_prompt_title, articleText) + Prefs.donationReminderConfig.donateAmount + } + val donationAmountText = DonateUtil.currencyFormat.format(donateAmount) + val titleText = if (isWrapUpEnabled) { + if (DonationReminderAbTest().group == GROUP_2) { + context.getString(R.string.donation_reminders_wrap_up_title) + } else { + context.getString(R.string.donation_reminders_eoe_title) + } + } else { + if (config.goalReachedCount == GROUP_2) { + context.getString(R.string.donation_reminders_first_milestone_reached_prompt_title, articleText, donationAmountText) + } else { + context.getString(R.string.donation_reminders_subsequent_milestone_reached_prompt_title, articleText) + } } val dateText = DateUtil.getMMMMdYYYY(Date(config.setupTimestamp)) - val messageText = context.getString(R.string.donation_reminders_prompt_message_v2, dateText, articleText, donationAmount) - val positiveButtonText = context.getString(R.string.donation_reminders_prompt_positive_button_v2) - val negativeButtonText = context.getString(R.string.donation_reminders_prompt_negative_button) + val messageText = if (isWrapUpEnabled) { + if (DonationReminderAbTest().group == GROUP_2) { + context.getString(R.string.donation_reminders_wrap_up_message) + } else { + context.getString(R.string.donation_reminders_eoe_message, donationAmountText) + } + } else { + context.getString(R.string.donation_reminders_prompt_message_v2, dateText, articleText, donationAmountText) + } + val positiveButtonText = if (isWrapUpEnabled) { + if (DonationReminderAbTest().group == GROUP_2) { + context.getString(R.string.donation_reminders_wrap_up_share_feedback_button) + } else { + context.getString(R.string.donation_reminders_eoe_give_monthly_button) + } + } else { + context.getString(R.string.donation_reminders_prompt_positive_button_v2) + } + val negativeButtonText = if (isWrapUpEnabled) { + context.getString(R.string.donation_reminders_settings_no_thanks_btn_label) + } else { + context.getString(R.string.donation_reminders_prompt_negative_button) + } + if (isWrapUpEnabled) { + binding.donationReminderCardView.showWrapUpContainer() + } binding.donationReminderCardView.setTitle(titleText) binding.donationReminderCardView.setMessage(messageText) binding.donationReminderCardView.setPositiveButton(positiveButtonText) { DonationReminderHelper.dismissReminder() - callback?.donationReminderCardPositiveClicked() + callback?.donationReminderCardPositiveClicked(reminderCardType) } binding.donationReminderCardView.setNegativeButton(negativeButtonText) { binding.donationReminderCardView.isVisible = false DonationReminderHelper.dismissReminder() - callback?.donationReminderCardNegativeClicked() + callback?.donationReminderCardNegativeClicked(reminderCardType) } } } fun maybeShowDonationReminderCard() { - if (DonationReminderHelper.shouldShowReminderNow()) { - DonorExperienceEvent.logDonationReminderAction( - activeInterface = "reminder_milestone", - action = "impression" - ) + if (DonationReminderHelper.shouldShowReminderNow() || DonationReminderHelper.isWrapUpEnabled) { + if (!DonationReminderHelper.isWrapUpEnabled) { + DonorExperienceEvent.logDonationReminderAction( + activeInterface = "reminder_milestone", + action = "impression" + ) + } updateDonationReminderCardContent(Prefs.donationReminderConfig) binding.donationReminderCardView.isVisible = true } else { diff --git a/app/src/main/java/org/wikipedia/settings/Prefs.kt b/app/src/main/java/org/wikipedia/settings/Prefs.kt index b570937b702..687f9fe5974 100644 --- a/app/src/main/java/org/wikipedia/settings/Prefs.kt +++ b/app/src/main/java/org/wikipedia/settings/Prefs.kt @@ -908,6 +908,10 @@ object Prefs { ) ?: DonationReminderConfig() set(types) = PrefsIoUtil.setString(R.string.preference_key_donation_reminder_config, JsonUtil.encodeToString(types)) + var donationReminderDevWrapUp + get() = PrefsIoUtil.getBoolean(R.string.preference_key_donation_reminders_dev_wrap_up_enabled, false) + set(value) = PrefsIoUtil.setBoolean(R.string.preference_key_donation_reminders_dev_wrap_up_enabled, value) + var activityTabModules: ActivityTabModules get() = JsonUtil.decodeFromString(PrefsIoUtil.getString(R.string.preference_key_activity_tab_modules, null)) ?: ActivityTabModules() diff --git a/app/src/main/java/org/wikipedia/settings/dev/DeveloperSettingsPreferenceLoader.kt b/app/src/main/java/org/wikipedia/settings/dev/DeveloperSettingsPreferenceLoader.kt index f94c5232b1b..e232f2ff04a 100644 --- a/app/src/main/java/org/wikipedia/settings/dev/DeveloperSettingsPreferenceLoader.kt +++ b/app/src/main/java/org/wikipedia/settings/dev/DeveloperSettingsPreferenceLoader.kt @@ -244,6 +244,7 @@ internal class DeveloperSettingsPreferenceLoader(fragment: PreferenceFragmentCom } findPreference(R.string.preference_key_donation_reminders_dev_reset).onPreferenceClickListener = Preference.OnPreferenceClickListener { Prefs.donationReminderConfig = DonationReminderConfig() + Prefs.donationReminderDevWrapUp = false Toast.makeText(activity, "donationReminderConfig has been reset", Toast.LENGTH_SHORT).show() fragment.requireActivity().finish() true @@ -256,6 +257,14 @@ internal class DeveloperSettingsPreferenceLoader(fragment: PreferenceFragmentCom fragment.requireActivity().finish() true } + findPreference(R.string.preference_key_donation_reminders_dev_wrap_up_enabled).onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val isWrapUpEnabled = newValue as Boolean + Prefs.donationReminderDevWrapUp = isWrapUpEnabled + Prefs.donationReminderConfig = Prefs.donationReminderConfig.copy( + wrapUpEnabled = isWrapUpEnabled + ) + true + } (findPreference(R.string.preference_key_yir_survey_state) as ListPreference).apply { val states = YearInReviewSurveyState.entries val names = states.map { it.name }.toTypedArray() diff --git a/app/src/main/java/org/wikipedia/views/SurveyDialog.kt b/app/src/main/java/org/wikipedia/views/SurveyDialog.kt index 4fa40b803e5..fd833352128 100644 --- a/app/src/main/java/org/wikipedia/views/SurveyDialog.kt +++ b/app/src/main/java/org/wikipedia/views/SurveyDialog.kt @@ -66,6 +66,55 @@ object SurveyDialog { dialog = dialogBuilder.show() } + fun showDonationReminderFeedbackDialog( + activity: Activity, + onImpression: () -> Unit, + onCancel: () -> Unit, + onSubmit: (feedbackOption: Int?, feedbackText: String) -> Unit + ) { + val maxCharacter = 250 + var dialog: AlertDialog? = null + val binding = DialogFeedbackOptionsBinding.inflate(activity.layoutInflater) + binding.titleText.text = activity.getString(R.string.donation_reminders_wrap_up_survey_title) + binding.messageText.text = activity.getString(R.string.donation_reminders_wrap_up_survey_message) + binding.optionSatisfied.text = activity.getString(R.string.donation_reminders_wrap_up_survey_option_keep_it) + binding.optionNeutral.text = activity.getString(R.string.donation_reminders_wrap_up_survey_option_remove_it) + binding.optionUnsatisfied.text = activity.getString(R.string.donation_reminders_wrap_up_survey_option_not_sure) + binding.feedbackInputContainer.isVisible = true + binding.feedbackInputContainer.isCounterEnabled = true + binding.feedbackInputContainer.counterMaxLength = maxCharacter + binding.feedbackInputContainer.hint = activity.getString(R.string.donation_reminders_wrap_up_survey_optional_hint) + binding.feedbackInput.filters = arrayOf(InputFilter.LengthFilter(maxCharacter)) + binding.feedbackInput.setOnFocusChangeListener { _, hasFocus -> + if (hasFocus) { + binding.dialogContainer.postDelayed({ + if (!activity.isDestroyed) { + binding.dialogContainer.fullScroll(ScrollView.FOCUS_DOWN) + } + }, 200) + } + } + + binding.cancelButton.setOnClickListener { + onCancel() + dialog?.dismiss() + } + binding.submitButton.setOnClickListener { + val feedbackOption = getSelectedOption(binding) + val feedbackText = binding.feedbackInput.text.toString() + onSubmit(feedbackOption, feedbackText) + FeedbackUtil.showMessage(activity, R.string.donation_reminders_wrap_up_survey_thank_you_message) + dialog?.dismiss() + } + + val dialogBuilder = MaterialAlertDialogBuilder(activity, R.style.AlertDialogTheme_AdjustResize) + .setCancelable(false) + .setView(binding.root) + + onImpression() + dialog = dialogBuilder.show() + } + private fun getSelectedOption(binding: DialogFeedbackOptionsBinding): Int? { val selectedId = binding.feedbackRadioGroup.checkedRadioButtonId return when (selectedId) { diff --git a/app/src/main/res/drawable/ic_open_in_new_black_16px.xml b/app/src/main/res/drawable/ic_open_in_new_black_16px.xml new file mode 100644 index 00000000000..2348d071c6c --- /dev/null +++ b/app/src/main/res/drawable/ic_open_in_new_black_16px.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_donation_reminder_card.xml b/app/src/main/res/layout/view_donation_reminder_card.xml index c3898bf0b19..f2060540aff 100644 --- a/app/src/main/res/layout/view_donation_reminder_card.xml +++ b/app/src/main/res/layout/view_donation_reminder_card.xml @@ -12,6 +12,54 @@ android:orientation="vertical" android:background="?attr/background_color"> + + + + + + + + + + donationReminder donationReminderDevReset donationReminderDevResetSeenDate + donationReminderDevWrapUpEnabled donations activityTabModules activityTabOnboardingShown diff --git a/app/src/main/res/xml/developer_preferences.xml b/app/src/main/res/xml/developer_preferences.xml index 583559530cf..35477b8bafb 100644 --- a/app/src/main/res/xml/developer_preferences.xml +++ b/app/src/main/res/xml/developer_preferences.xml @@ -531,6 +531,10 @@ android:key="@string/preference_key_donation_reminders_dev_reset_seen_date" android:title="Remove the last prompt seen date." /> + +