diff --git a/PixelDefinitions/pixels/sync_promotion.json5 b/PixelDefinitions/pixels/sync_promotion.json5 new file mode 100644 index 000000000000..bb3b956bf7c9 --- /dev/null +++ b/PixelDefinitions/pixels/sync_promotion.json5 @@ -0,0 +1,23 @@ +{ + "sync_setup_promo_bookmark_added_dialog_shown": { + "description": "User added a bookmark and we showed the sync setup promo in the bookmark added dialog", + "owners": ["CDRussell"], + "triggers": ["other"], + "suffixes": ["form_factor"], + "parameters": ["appVersion"] + }, + "sync_setup_promo_bookmark_added_dialog_dismissed": { + "description": "User manually chose to hide the sync setup promo in the bookmark added dialog", + "owners": ["CDRussell"], + "triggers": ["other"], + "suffixes": ["form_factor"], + "parameters": ["appVersion"] + }, + "sync_setup_promo_bookmark_added_dialog_confirmed": { + "description": "User chose to set up sync from the promo in the bookmark added dialog", + "owners": ["CDRussell"], + "triggers": ["other"], + "suffixes": ["form_factor"], + "parameters": ["appVersion"] + } +} diff --git a/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialog.kt b/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialog.kt index 63443eb6762d..06c005cb8b28 100644 --- a/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialog.kt +++ b/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialog.kt @@ -31,7 +31,7 @@ import android.widget.LinearLayout import androidx.core.view.children import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope -import com.duckduckgo.app.bookmarks.BookmarkAddedPromotionPlugin +import com.duckduckgo.app.bookmarks.BookmarkAddedDialogPlugin import com.duckduckgo.app.browser.R import com.duckduckgo.app.browser.databinding.BottomSheetAddBookmarkBinding import com.duckduckgo.common.ui.view.gone @@ -54,7 +54,7 @@ import com.google.android.material.R as MaterialR class BookmarkAddedConfirmationDialog( context: Context, private val bookmarkFolder: BookmarkFolder?, - private val promoPlugins: PluginPoint, + private val promoPlugins: PluginPoint, ) : BottomSheetDialog(context) { abstract class EventListener { diff --git a/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialogFactory.kt b/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialogFactory.kt index 7d46dbdd6314..2e5e28066b0d 100644 --- a/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialogFactory.kt +++ b/app/src/main/java/com/duckduckgo/app/bookmarks/dialog/BookmarkAddedConfirmationDialogFactory.kt @@ -17,7 +17,7 @@ package com.duckduckgo.app.bookmarks.dialog import android.content.Context -import com.duckduckgo.app.bookmarks.BookmarkAddedPromotionPlugin +import com.duckduckgo.app.bookmarks.BookmarkAddedDialogPlugin import com.duckduckgo.common.utils.plugins.PluginPoint import com.duckduckgo.di.scopes.AppScope import com.duckduckgo.savedsites.api.models.BookmarkFolder @@ -31,7 +31,7 @@ interface BookmarkAddedConfirmationDialogFactory { @ContributesBinding(AppScope::class) class ReadyBookmarkAddedConfirmationDialogFactory @Inject constructor( - private val plugins: PluginPoint, + private val plugins: PluginPoint, ) : BookmarkAddedConfirmationDialogFactory { override fun create(context: Context, bookmarkFolder: BookmarkFolder?): BookmarkAddedConfirmationDialog { return BookmarkAddedConfirmationDialog(context, bookmarkFolder, plugins) diff --git a/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt b/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt index 4c3eab4b9352..3d21ab209d19 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/di/BrowserModule.kt @@ -25,7 +25,7 @@ import androidx.datastore.preferences.preferencesDataStore import androidx.work.WorkManager import com.duckduckgo.adclick.api.AdClickManager import com.duckduckgo.anvil.annotations.ContributesPluginPoint -import com.duckduckgo.app.bookmarks.BookmarkAddedPromotionPlugin +import com.duckduckgo.app.bookmarks.BookmarkAddedDialogPlugin import com.duckduckgo.app.browser.* import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector import com.duckduckgo.app.browser.addtohome.AddToHomeSystemCapabilityDetector @@ -389,5 +389,5 @@ class BrowserModule { @Qualifier annotation class IndonesiaNewTabSection -@ContributesPluginPoint(scope = AppScope::class, boundType = BookmarkAddedPromotionPlugin::class) -private interface BookmarkAddedPromotionPluginPoint +@ContributesPluginPoint(scope = AppScope::class, boundType = BookmarkAddedDialogPlugin::class) +private interface BookmarkAddedDialogPluginPoint diff --git a/app/src/main/res/layout/bottom_sheet_add_bookmark.xml b/app/src/main/res/layout/bottom_sheet_add_bookmark.xml index e8cc5acacc1a..b9eb2898b8b0 100644 --- a/app/src/main/res/layout/bottom_sheet_add_bookmark.xml +++ b/app/src/main/res/layout/bottom_sheet_add_bookmark.xml @@ -21,8 +21,7 @@ android:layout_height="match_parent" android:background="@drawable/rounded_top_corners_bottom_sheet_drawable" android:orientation="vertical" - android:paddingTop="@dimen/actionBottomSheetVerticalPadding" - android:paddingBottom="@dimen/actionBottomSheetVerticalPadding"> + android:paddingTop="@dimen/actionBottomSheetVerticalPadding"> + android:layout_marginTop="@dimen/keyline_2" + android:background="?attr/daxColorBackground" + android:orientation="vertical" + android:paddingStart="@dimen/keyline_4" + android:paddingTop="@dimen/keyline_4" + android:paddingEnd="@dimen/keyline_4" + android:paddingBottom="@dimen/keyline_4" /> \ No newline at end of file diff --git a/browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedPromotionPlugin.kt b/browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedDialogPlugin.kt similarity index 90% rename from browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedPromotionPlugin.kt rename to browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedDialogPlugin.kt index 74ee4f5e76f2..35873b9792b2 100644 --- a/browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedPromotionPlugin.kt +++ b/browser-api/src/main/java/com/duckduckgo/app/bookmarks/BookmarkAddedDialogPlugin.kt @@ -18,7 +18,7 @@ package com.duckduckgo.app.bookmarks import android.view.View -interface BookmarkAddedPromotionPlugin { +interface BookmarkAddedDialogPlugin { /** * Returns a view to be displayed in the bookmark added confirmation dialog, or null if the promotion should not be shown. @@ -27,6 +27,6 @@ interface BookmarkAddedPromotionPlugin { suspend fun getView(): View? companion object { - const val PRIORITY_KEY_BOOKMARK_ADDED_PROMOTION = 100 + const val PRIORITY_KEY_SETUP_SYNC = 100 } } diff --git a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/pixels/SyncPixels.kt b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/pixels/SyncPixels.kt index 479cabf974ad..9f626397f3a2 100644 --- a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/pixels/SyncPixels.kt +++ b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/pixels/SyncPixels.kt @@ -115,6 +115,9 @@ interface SyncPixels { fun fireSetupDeepLinkFlowAbandoned() fun fireUserConfirmedToTurnOffSync() fun fireUserConfirmedToTurnOffSyncAndDelete(connectedDevices: Int) + fun fireSetupSyncPromoBookmarkAddedDialogDismissed() + fun fireSetupSyncPromoBookmarkAddedDialogConfirmed() + fun fireSetupSyncPromoBookmarkAddedDialogShown() } @ContributesBinding(AppScope::class) @@ -338,6 +341,18 @@ class RealSyncPixels @Inject constructor( pixel.fire(SyncPixelName.SYNC_USER_CONFIRMED_TO_TURN_OFF_SYNC_AND_DELETE, parameters = params) } + override fun fireSetupSyncPromoBookmarkAddedDialogDismissed() { + pixel.fire(SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_DISMISSED) + } + + override fun fireSetupSyncPromoBookmarkAddedDialogConfirmed() { + pixel.fire(SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_CONFIRMED) + } + + override fun fireSetupSyncPromoBookmarkAddedDialogShown() { + pixel.fire(SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_SHOWN) + } + override fun fireSyncBarcodeScreenShown(screenType: ScreenType) { val params = mapOf(SYNC_SETUP_SCREEN_TYPE to screenType.value) pixel.fire(SyncPixelName.SYNC_SETUP_BARCODE_SCREEN_SHOWN, parameters = params) @@ -452,6 +467,9 @@ enum class SyncPixelName(override val pixelName: String) : Pixel.PixelName { SYNC_SETUP_ENDED_SUCCESS("sync_setup_ended_successful"), SYNC_USER_CONFIRMED_TO_TURN_OFF_SYNC("sync_disabled"), SYNC_USER_CONFIRMED_TO_TURN_OFF_SYNC_AND_DELETE("sync_disabledanddeleted"), + SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_SHOWN("sync_setup_promo_bookmark_added_dialog_shown"), + SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_DISMISSED("sync_setup_promo_bookmark_added_dialog_dismissed"), + SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_CONFIRMED("sync_setup_promo_bookmark_added_dialog_confirmed"), } object SyncPixelParameters { @@ -485,6 +503,9 @@ object SyncPixelsRequiringDataCleaning : PixelParamRemovalPlugin { return listOf( SyncPixelName.SYNC_USER_CONFIRMED_TO_TURN_OFF_SYNC.pixelName to removeAtb(), SyncPixelName.SYNC_USER_CONFIRMED_TO_TURN_OFF_SYNC_AND_DELETE.pixelName to removeAtb(), + SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_SHOWN.pixelName to removeAtb(), + SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_DISMISSED.pixelName to removeAtb(), + SyncPixelName.SYNC_SETUP_PROMO_BOOKMARK_ADDED_DIALOG_CONFIRMED.pixelName to removeAtb(), ) } } diff --git a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/promotion/bookmarks/addeddialog/SetupSyncBookmarkAddedPromo.kt b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/promotion/bookmarks/addeddialog/SetupSyncBookmarkAddedPromo.kt index b33e519bb485..c66aa2046803 100644 --- a/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/promotion/bookmarks/addeddialog/SetupSyncBookmarkAddedPromo.kt +++ b/sync/sync-impl/src/main/java/com/duckduckgo/sync/impl/promotion/bookmarks/addeddialog/SetupSyncBookmarkAddedPromo.kt @@ -22,7 +22,7 @@ import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import com.duckduckgo.anvil.annotations.PriorityKey -import com.duckduckgo.app.bookmarks.BookmarkAddedPromotionPlugin +import com.duckduckgo.app.bookmarks.BookmarkAddedDialogPlugin import com.duckduckgo.common.ui.menu.PopupMenu import com.duckduckgo.common.ui.view.gone import com.duckduckgo.common.ui.view.listitem.OneLineListItem @@ -33,20 +33,22 @@ import com.duckduckgo.sync.api.SyncActivityWithEmptyParams import com.duckduckgo.sync.api.SyncState import com.duckduckgo.sync.api.SyncStateMonitor import com.duckduckgo.sync.impl.R +import com.duckduckgo.sync.impl.pixels.SyncPixels import com.duckduckgo.sync.impl.promotion.SyncPromotions import com.squareup.anvil.annotations.ContributesMultibinding import kotlinx.coroutines.launch import javax.inject.Inject @ContributesMultibinding(scope = ActivityScope::class) -@PriorityKey(BookmarkAddedPromotionPlugin.PRIORITY_KEY_BOOKMARK_ADDED_PROMOTION) +@PriorityKey(BookmarkAddedDialogPlugin.PRIORITY_KEY_SETUP_SYNC) class SetupSyncBookmarkAddedPromo @Inject constructor( private val globalActivityStarter: GlobalActivityStarter, private val dispatchers: DispatcherProvider, private val activity: AppCompatActivity, private val syncPromotions: SyncPromotions, private val syncStateMonitor: SyncStateMonitor, -) : BookmarkAddedPromotionPlugin { + private val syncPixels: SyncPixels, +) : BookmarkAddedDialogPlugin { @SuppressLint("InflateParams") override suspend fun getView(): View? { @@ -55,8 +57,12 @@ class SetupSyncBookmarkAddedPromo @Inject constructor( } val root = LayoutInflater.from(activity).inflate(R.layout.view_sync_setup_bookmark_added_promo, null) as OneLineListItem - root.setOnClickListener { onLaunchSyncFlow(activity) } + root.setOnClickListener { + onLaunchSyncFlow(activity) + syncPixels.fireSetupSyncPromoBookmarkAddedDialogConfirmed() + } root.configureOverflowMenu() + root.configureViewAttachedListener() activity.lifecycleScope.launch { syncStateMonitor.syncState().collect { syncState -> onSyncStateAvailable(syncState, root) } @@ -102,10 +108,23 @@ class SetupSyncBookmarkAddedPromo @Inject constructor( activity.lifecycleScope.launch(dispatchers.main()) { rootView.gone() syncPromotions.recordBookmarkAddedDialogPromotionDismissed() + syncPixels.fireSetupSyncPromoBookmarkAddedDialogDismissed() } } } return popupMenu } + + private fun OneLineListItem.configureViewAttachedListener() { + this.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) { + syncPixels.fireSetupSyncPromoBookmarkAddedDialogShown() + } + + override fun onViewDetachedFromWindow(v: View) { + // no-op + } + }) + } }