From 94ae3390ba37bdb90152fcfa2308ceb3372f599e Mon Sep 17 00:00:00 2001 From: VaiTon Date: Mon, 28 Jun 2021 23:42:24 +0200 Subject: [PATCH] feat: add analytics opt in in welcome screen --- .../features/welcome/WelcomeActivity.kt | 136 ++++++++++-------- .../features/welcome/WelcomePageAdapter.kt | 7 +- .../features/welcome/WelcomeScreen.kt | 23 +++ .../openfood/network/services/ProductsAPI.kt | 4 +- .../scrachx/openfood/utils/PrefManager.kt | 12 +- .../github/scrachx/openfood/utils/Utils.kt | 9 +- .../res/drawable/ic_analytics_white_24.xml | 10 ++ ..._slide4.xml => welcome_slide_ecoscore.xml} | 6 +- ...ome_slide1.xml => welcome_slide_intro.xml} | 2 +- .../main/res/layout/welcome_slide_matomo.xml | 61 ++++++++ ...come_slide3.xml => welcome_slide_nova.xml} | 0 ...lide2.xml => welcome_slide_nutriscore.xml} | 0 app/src/main/res/values/colors.xml | 23 +-- 13 files changed, 194 insertions(+), 99 deletions(-) create mode 100644 app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeScreen.kt create mode 100644 app/src/main/res/drawable/ic_analytics_white_24.xml rename app/src/main/res/layout/{welcome_slide4.xml => welcome_slide_ecoscore.xml} (90%) rename app/src/main/res/layout/{welcome_slide1.xml => welcome_slide_intro.xml} (96%) create mode 100644 app/src/main/res/layout/welcome_slide_matomo.xml rename app/src/main/res/layout/{welcome_slide3.xml => welcome_slide_nova.xml} (100%) rename app/src/main/res/layout/{welcome_slide2.xml => welcome_slide_nutriscore.xml} (100%) diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeActivity.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeActivity.kt index d47597351ddf..d90fecf8d40a 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeActivity.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeActivity.kt @@ -17,26 +17,31 @@ package openfoodfacts.github.scrachx.openfood.features.welcome import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.content.pm.ActivityInfo import android.graphics.Color import android.os.Build import android.os.Bundle -import android.view.View import android.view.Window import android.view.WindowManager import android.widget.TextView +import androidx.core.content.edit +import androidx.core.content.res.ResourcesCompat import androidx.core.text.HtmlCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager.OnPageChangeListener import dagger.hilt.android.AndroidEntryPoint import openfoodfacts.github.scrachx.openfood.R +import openfoodfacts.github.scrachx.openfood.analytics.MatomoAnalytics import openfoodfacts.github.scrachx.openfood.databinding.ActivityWelcomeBinding import openfoodfacts.github.scrachx.openfood.features.MainActivity import openfoodfacts.github.scrachx.openfood.features.shared.BaseActivity import openfoodfacts.github.scrachx.openfood.utils.PrefManager +import openfoodfacts.github.scrachx.openfood.utils.darken +import openfoodfacts.github.scrachx.openfood.utils.lighten +import javax.inject.Inject /** * This is the on boarding activity shown on first-run. @@ -52,48 +57,45 @@ class WelcomeActivity : BaseActivity() { private var _binding: ActivityWelcomeBinding? = null private val binding get() = _binding!! - private val layouts = intArrayOf( - R.layout.welcome_slide1, - R.layout.welcome_slide2, - R.layout.welcome_slide3, - R.layout.welcome_slide4 - ) private lateinit var prefManager: PrefManager - private var lastPage = false + + private val screens = WelcomeScreen.values() + + + @Inject + lateinit var matomoAnalytics: MatomoAnalytics + + @Inject + lateinit var sharedPreferences: SharedPreferences private val viewPagerPageChangeListener = object : OnPageChangeListener { - private var currentState = 0 - override fun onPageSelected(position: Int) { - refreshBottomDots(position) - if (position == layouts.lastIndex) { - binding.btnNext.text = getString(R.string.start) - binding.btnSkip.visibility = View.GONE - lastPage = true - } else { - binding.btnNext.text = getString(R.string.next) - binding.btnSkip.visibility = View.VISIBLE - lastPage = false - } - } - /** - * If user is on the last page and tries to swipe towards the next page on right then the value of - * positionOffset returned is always 0. On the other hand if the user tries to swipe towards the - * previous page on the left then the value of positionOffset returned is 0.999 and decreases as the - * user continues to swipe in the same direction. Also whenever a user tries to swipe in any - * direction the state is changed from idle to dragging and onPageScrollStateChanged is called. - * Therefore if the user is on the last page and the value of positionOffset is 0 and state is - * dragging it means that the user is trying to go to the next page on right from the last page and - * hence MainActivity is started in this case. - */ - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { - if (lastPage && positionOffset == 0f && currentState == ViewPager.SCROLL_STATE_DRAGGING) { - launchHomeScreen() - } - } + override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) = Unit + override fun onPageScrollStateChanged(state: Int) = Unit - override fun onPageScrollStateChanged(state: Int) { - currentState = state + override fun onPageSelected(position: Int) { + refreshBottomBar(position) + + when (WelcomeScreen[position]) { + WelcomeScreen.MATOMO -> { + binding.btnNext.setText(R.string.preference_analytics_bottom_sheet_grant_button) + binding.btnSkip.setText(R.string.preference_analytics_bottom_sheet_decline_button) + + binding.btnNext.setTextColor(ResourcesCompat.getColor(resources, android.R.color.black, theme)) + binding.btnSkip.setTextColor(ResourcesCompat.getColor(resources, android.R.color.black, theme)) + + binding.btnNext.setOnClickListener { saveThenLaunchHome(true) } + binding.btnSkip.setOnClickListener { saveThenLaunchHome(false) } + } + else -> { + binding.btnNext.setTextColor(ResourcesCompat.getColor(resources, android.R.color.white, theme)) + binding.btnSkip.setTextColor(ResourcesCompat.getColor(resources, android.R.color.white, theme)) + + binding.btnNext.setText(R.string.next) + binding.btnSkip.setText(R.string.skip) + setOnClicks() + } + } } } @@ -103,31 +105,26 @@ class WelcomeActivity : BaseActivity() { if (resources.getBoolean(R.bool.portrait_only)) { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } + _binding = ActivityWelcomeBinding.inflate(layoutInflater) setContentView(binding.root) + prefManager = PrefManager(this) if (!prefManager.isFirstTimeLaunch) { - launchHomeScreen() + launchHome() finish() } WindowCompat.setDecorFitsSystemWindows(window, false) WindowInsetsControllerCompat(window, binding.root).hide(WindowInsetsCompat.Type.statusBars()) - refreshBottomDots(0) + refreshBottomBar(0) changeStatusBarColor() - binding.viewPager.adapter = WelcomePageAdapter(layoutInflater, layouts) + binding.viewPager.adapter = WelcomePageAdapter(layoutInflater) binding.viewPager.addOnPageChangeListener(viewPagerPageChangeListener) - binding.btnSkip.setOnClickListener { launchHomeScreen() } - binding.btnNext.setOnClickListener { - if (nextItem < layouts.size) { - binding.viewPager.currentItem = nextItem - } else { - launchHomeScreen() - } - } + setOnClicks() } override fun onDestroy() { @@ -135,26 +132,41 @@ class WelcomeActivity : BaseActivity() { super.onDestroy() } - private fun refreshBottomDots(currentPage: Int) { - val colorsActive = resources.getIntArray(R.array.array_dot_active) - val colorsInactive = resources.getIntArray(R.array.array_dot_inactive) + private fun setOnClicks() { + binding.btnSkip.setOnClickListener { binding.viewPager.currentItem = screens.size - 1 } + binding.btnNext.setOnClickListener { binding.viewPager.currentItem = nextItem } + } + + private fun saveThenLaunchHome(grant: Boolean) { + saveAnalyticsReportingPref(grant) + matomoAnalytics.onAnalyticsEnabledToggled(grant) + launchHome() + } + + private fun saveAnalyticsReportingPref(value: Boolean) { + sharedPreferences.edit { + putBoolean(getString(R.string.pref_analytics_reporting_key), value) + } + } + + private fun launchHome() { + prefManager.isFirstTimeLaunch = false + startActivity(Intent(this@WelcomeActivity, MainActivity::class.java)) + finish() + } + + private fun refreshBottomBar(currentPage: Int) { binding.layoutDots.removeAllViews() - val dots = (1..layouts.size).map { + val dots = (0..screens.lastIndex).map { TextView(this).apply { text = HtmlCompat.fromHtml("•", HtmlCompat.FROM_HTML_MODE_COMPACT) textSize = 35f - setTextColor(colorsInactive[currentPage]) + setTextColor(WelcomeScreen[currentPage].color.lighten(0.85f)) binding.layoutDots.addView(this) } } - dots[currentPage].setTextColor(colorsActive[currentPage]) - } - - private fun launchHomeScreen() { - prefManager.isFirstTimeLaunch = false - startActivity(Intent(this@WelcomeActivity, MainActivity::class.java)) - finish() + dots[currentPage].setTextColor(WelcomeScreen[currentPage].color.darken(0.1f)) } private val nextItem get() = binding.viewPager.currentItem + 1 diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomePageAdapter.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomePageAdapter.kt index b524592411b1..e0824591655b 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomePageAdapter.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomePageAdapter.kt @@ -3,20 +3,19 @@ package openfoodfacts.github.scrachx.openfood.features.welcome import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.annotation.StringRes import androidx.viewpager.widget.PagerAdapter class WelcomePageAdapter( private val layoutInflater: LayoutInflater, - @param:StringRes private val layouts: IntArray ) : PagerAdapter() { override fun instantiateItem(container: ViewGroup, position: Int): Any { - val view = layoutInflater.inflate(layouts[position], container, false) + val layout = WelcomeScreen.values()[position].layout + val view = layoutInflater.inflate(layout, container, false) container.addView(view) return view } - override fun getCount() = layouts.size + override fun getCount() = WelcomeScreen.values().size override fun isViewFromObject(view: View, obj: Any) = view === obj diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeScreen.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeScreen.kt new file mode 100644 index 000000000000..21ee00f91eca --- /dev/null +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/welcome/WelcomeScreen.kt @@ -0,0 +1,23 @@ +package openfoodfacts.github.scrachx.openfood.features.welcome + +import androidx.annotation.ColorRes +import androidx.annotation.StringRes +import openfoodfacts.github.scrachx.openfood.R + +internal enum class WelcomeScreen(@StringRes layoutRes: Int, @ColorRes colorRes: Int) { + INTRO(R.layout.welcome_slide_intro, R.color.bg_welcome_intro), + NUTRISCORE(R.layout.welcome_slide_nutriscore, R.color.bg_welcome_nutriscore), + NOVA(R.layout.welcome_slide_nova, R.color.bg_welcome_nova), + ECOSCORE(R.layout.welcome_slide_ecoscore, R.color.bg_welcome_ecoscore), + MATOMO(R.layout.welcome_slide_matomo, R.color.bg_welcome_matomo); + + @StringRes + val layout = layoutRes + + @ColorRes + val color = colorRes + + companion object { + operator fun get(position: Int) = values()[position] + } +} \ No newline at end of file diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt index 698d32903a69..089774ddcf29 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt @@ -111,7 +111,7 @@ interface ProductsAPI { suspend fun getSuggestions( @Query("tagtype") tagType: String, @Query("term") term: String - ): List + ): ArrayList @GET("brand/{brand}/{page}.json") @@ -332,7 +332,7 @@ interface ProductsAPI { * This method gives the news in all languages */ @GET("/files/tagline/tagline-$FLAVOR_versionCode.json") - fun getTagline(@Header("User-Agent") header: String): List + fun getTagline(@Header("User-Agent") header: String): ArrayList /** * Returns images for the current product diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt index c4037cb4a74a..de6e5e6da5d1 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt @@ -11,24 +11,18 @@ class PrefManager(context: Context) { var isFirstTimeLaunch: Boolean get() { val actualTime = System.currentTimeMillis() + // First time launch if (pref.getLong(FIRST_TIME_LAUNCH_TIME, actualTime) == actualTime) { - // First time launch - // Save first launch time pref.edit { putLong(FIRST_TIME_LAUNCH_TIME, actualTime) } } return pref.getBoolean(IS_FIRST_TIME_LAUNCH, true) } - // Save first launch time - set(isFirstTime) { - pref.edit { putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime) } - } + set(isFirstTime) = pref.edit { putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime) } var userAskedToRate: Boolean get() = pref.getBoolean(USER_ASKED_TO_RATE, false) - set(userAskedToRate) { - pref.edit { putBoolean(USER_ASKED_TO_RATE, userAskedToRate) } - } + set(userAskedToRate) = pref.edit { putBoolean(USER_ASKED_TO_RATE, userAskedToRate) } val firstTimeLaunchTime: Long get() = pref.getLong(FIRST_TIME_LAUNCH_TIME, System.currentTimeMillis()) diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Utils.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Utils.kt index 7ec85cd39a9c..23764ab1f555 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Utils.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Utils.kt @@ -24,6 +24,7 @@ import android.content.pm.PackageManager.PERMISSION_GRANTED import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas +import android.graphics.Color import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.Uri @@ -36,10 +37,12 @@ import android.view.View import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.ImageView +import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils import androidx.core.net.toUri import androidx.core.text.inSpans import androidx.core.view.children @@ -343,4 +346,8 @@ internal fun RequestCreator.into(target: ImageView, onSuccess: () -> Unit) { override fun onSuccess() = onSuccess() override fun onError(e: Exception) = throw e }) -} \ No newline at end of file +} + + +fun @receiver:ColorInt Int.darken(ratio: Float) = ColorUtils.blendARGB(this, Color.BLACK, ratio) +fun @receiver:ColorInt Int.lighten(ratio: Float) = ColorUtils.blendARGB(this, Color.WHITE, ratio) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_analytics_white_24.xml b/app/src/main/res/drawable/ic_analytics_white_24.xml new file mode 100644 index 000000000000..4ee1d664cfe9 --- /dev/null +++ b/app/src/main/res/drawable/ic_analytics_white_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/welcome_slide4.xml b/app/src/main/res/layout/welcome_slide_ecoscore.xml similarity index 90% rename from app/src/main/res/layout/welcome_slide4.xml rename to app/src/main/res/layout/welcome_slide_ecoscore.xml index 77b0df8bd71a..619945e95c0f 100644 --- a/app/src/main/res/layout/welcome_slide4.xml +++ b/app/src/main/res/layout/welcome_slide_ecoscore.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/brand_green_dark" + android:background="@color/bg_welcome_ecoscore" android:gravity="center"> + android:contentDescription="TODO" + app:srcCompat="@drawable/ic_ecoscore_b" /> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/welcome_slide3.xml b/app/src/main/res/layout/welcome_slide_nova.xml similarity index 100% rename from app/src/main/res/layout/welcome_slide3.xml rename to app/src/main/res/layout/welcome_slide_nova.xml diff --git a/app/src/main/res/layout/welcome_slide2.xml b/app/src/main/res/layout/welcome_slide_nutriscore.xml similarity index 100% rename from app/src/main/res/layout/welcome_slide2.xml rename to app/src/main/res/layout/welcome_slide_nutriscore.xml diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e8d542523dc1..f5d80d9584fc 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -84,10 +84,12 @@ #cfd8dc - #f64c73 - #20d2bb - #3395ff - #c873f4 + #f64c73 + #20d2bb + #3395ff + @color/brand_green_dark + @color/blue_grey_100 + #d1395c #14a895 #2278d4 @@ -100,19 +102,6 @@ @color/primary_dark @color/primary_dark - - @color/dot_light_screen1 - @color/dot_light_screen2 - @color/dot_light_screen3 - @color/dot_light_screen4 - - - - @color/dot_dark_screen1 - @color/dot_dark_screen2 - @color/dot_dark_screen3 - @color/dot_dark_screen4 - #795548