Add promotional apps section on ForYou page

This commit is contained in:
Rahul Kumar Patel
2021-05-14 02:02:31 +05:30
parent 02fbb5f9bd
commit 00e24e5125
5 changed files with 74 additions and 29 deletions

View File

@@ -44,7 +44,7 @@ open class GenericCarouselController(private val callbacks: Callbacks) :
open fun applyFilter(streamBundle: StreamCluster): Boolean { open fun applyFilter(streamBundle: StreamCluster): Boolean {
return streamBundle.clusterTitle.isNotBlank() //Filter noisy cluster return streamBundle.clusterTitle.isNotBlank() //Filter noisy cluster
&& streamBundle.clusterAppList.isNotEmpty() //Filter empty clusters && streamBundle.clusterAppList.isNotEmpty() //Filter empty clusters
&& streamBundle.clusterAppList.count() > 1 //Filter clusters with single apps (mostly promotions) && streamBundle.clusterAppList.count() >= 1 //Filter clusters with single apps (mostly promotions)
} }
override fun buildModels(streamBundle: StreamBundle?) { override fun buildModels(streamBundle: StreamBundle?) {

View File

@@ -26,12 +26,12 @@ import com.airbnb.epoxy.CallbackProp
import com.airbnb.epoxy.ModelProp import com.airbnb.epoxy.ModelProp
import com.airbnb.epoxy.ModelView import com.airbnb.epoxy.ModelView
import com.airbnb.epoxy.OnViewRecycled import com.airbnb.epoxy.OnViewRecycled
import com.aurora.gplayapi.data.models.Artwork
import com.aurora.store.R
import com.aurora.store.databinding.ViewScreenshotMiniBinding
import com.aurora.extensions.clear import com.aurora.extensions.clear
import com.aurora.extensions.load import com.aurora.extensions.load
import com.aurora.extensions.px import com.aurora.extensions.px
import com.aurora.gplayapi.data.models.Artwork
import com.aurora.store.R
import com.aurora.store.databinding.ViewScreenshotMiniBinding
import com.aurora.store.view.epoxy.views.BaseView import com.aurora.store.view.epoxy.views.BaseView
import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
@@ -79,7 +79,11 @@ class MiniScreenshotView : RelativeLayout {
@ModelProp @ModelProp
fun artwork(artwork: Artwork) { fun artwork(artwork: Artwork) {
normalizeSize(artwork) normalizeSize(artwork)
B.img.load("${artwork.url}=rw-w480-v1-e15", DrawableTransitionOptions.withCrossFade()) { val imgUrl = if (artwork.url.endsWith(".webp"))
artwork.url
else
"${artwork.url}=rw-w480-v1-e15"
B.img.load(imgUrl, DrawableTransitionOptions.withCrossFade()) {
placeholder(R.drawable.bg_rounded) placeholder(R.drawable.bg_rounded)
transform(RoundedCorners(8.px.toInt())) transform(RoundedCorners(8.px.toInt()))
} }

View File

@@ -26,12 +26,12 @@ import com.airbnb.epoxy.CallbackProp
import com.airbnb.epoxy.ModelProp import com.airbnb.epoxy.ModelProp
import com.airbnb.epoxy.ModelView import com.airbnb.epoxy.ModelView
import com.airbnb.epoxy.OnViewRecycled import com.airbnb.epoxy.OnViewRecycled
import com.aurora.gplayapi.data.models.Artwork
import com.aurora.store.R
import com.aurora.store.databinding.ViewScreenshotBinding
import com.aurora.extensions.clear import com.aurora.extensions.clear
import com.aurora.extensions.load import com.aurora.extensions.load
import com.aurora.extensions.px import com.aurora.extensions.px
import com.aurora.gplayapi.data.models.Artwork
import com.aurora.store.R
import com.aurora.store.databinding.ViewScreenshotBinding
import com.aurora.store.view.epoxy.views.BaseView import com.aurora.store.view.epoxy.views.BaseView
import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
@@ -79,7 +79,11 @@ class ScreenshotView : RelativeLayout {
@ModelProp @ModelProp
fun artwork(artwork: Artwork) { fun artwork(artwork: Artwork) {
normalizeSize(artwork) normalizeSize(artwork)
B.img.load("${artwork.url}=rw-w480-v1-e15", DrawableTransitionOptions.withCrossFade()) { val imgUrl = if (artwork.url.endsWith(".webp"))
artwork.url
else
"${artwork.url}=rw-w480-v1-e15"
B.img.load(imgUrl, DrawableTransitionOptions.withCrossFade()) {
placeholder(R.drawable.bg_rounded) placeholder(R.drawable.bg_rounded)
transform(RoundedCorners(8.px.toInt())) transform(RoundedCorners(8.px.toInt()))
} }

View File

@@ -144,6 +144,7 @@ class AppDetailsActivity : BaseDetailsActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
B = ActivityDetailsBinding.inflate(layoutInflater) B = ActivityDetailsBinding.inflate(layoutInflater)
authData = AuthProvider.with(this).getAuthData()
setContentView(B.root) setContentView(B.root)
onNewIntent(intent) onNewIntent(intent)
@@ -174,7 +175,9 @@ class AppDetailsActivity : BaseDetailsActivity() {
} else { } else {
isExternal = true isExternal = true
app = App(packageName) app = App(packageName)
fetchCompleteApp() if (app.inPlayStore) {
fetchCompleteApp()
}
} }
} else { } else {
val rawApp: String? = intent.getStringExtra(Constants.STRING_EXTRA) val rawApp: String? = intent.getStringExtra(Constants.STRING_EXTRA)
@@ -183,7 +186,11 @@ class AppDetailsActivity : BaseDetailsActivity() {
isInstalled = PackageUtil.isInstalled(this, app.packageName) isInstalled = PackageUtil.isInstalled(this, app.packageName)
inflatePartialApp() inflatePartialApp()
fetchCompleteApp() if (app.inPlayStore) {
fetchCompleteApp()
} else {
inflateExtraDetails(app)
}
} else { } else {
close() close()
} }
@@ -317,7 +324,6 @@ class AppDetailsActivity : BaseDetailsActivity() {
private fun fetchCompleteApp() { private fun fetchCompleteApp() {
task { task {
authData = AuthProvider.with(this).getAuthData()
return@task AppDetailsHelper(authData) return@task AppDetailsHelper(authData)
.using(HttpClient.getPreferredClient()) .using(HttpClient.getPreferredClient())
.getAppByPackageName(app.packageName) .getAppByPackageName(app.packageName)
@@ -379,23 +385,30 @@ class AppDetailsActivity : BaseDetailsActivity() {
app?.let { app?.let {
B.viewFlipper.displayedChild = 1 B.viewFlipper.displayedChild = 1
inflateAppDescription(B.layoutDetailDescription, app) inflateAppDescription(B.layoutDetailDescription, app)
inflateAppRatingAndReviews(B.layoutDetailsReview, app)
inflateAppDevInfo(B.layoutDetailsDev, app) inflateAppDevInfo(B.layoutDetailsDev, app)
inflateAppPrivacy(B.layoutDetailsPrivacy, app) inflateAppPrivacy(B.layoutDetailsPrivacy, app)
inflateAppPermission(B.layoutDetailsPermissions, app) inflateAppPermission(B.layoutDetailsPermissions, app)
if (!authData.isAnonymous) { if (app.inPlayStore) {
app.testingProgram?.let { inflateAppRatingAndReviews(B.layoutDetailsReview, app)
if (it.isAvailable && it.isSubscribed) { if (!authData.isAnonymous) {
B.layoutDetailsApp.txtLine1.text = it.displayName app.testingProgram?.let {
if (it.isAvailable && it.isSubscribed) {
B.layoutDetailsApp.txtLine1.text = it.displayName
}
} }
inflateBetaSubscription(B.layoutDetailsBeta, app)
} }
inflateBetaSubscription(B.layoutDetailsBeta, app) if (Preferences.getBoolean(this, Preferences.PREFERENCE_SIMILAR)) {
} inflateAppStream(B.epoxyRecyclerStream, app)
}
if (Preferences.getBoolean(this, Preferences.PREFERENCE_SIMILAR)) { } else {
inflateAppStream(B.epoxyRecyclerStream, app) B.layoutDetailsReview.root.hide()
B.layoutDetailsBeta.root.hide()
B.epoxyRecyclerStream.hide()
} }
} }
} }
@@ -425,13 +438,16 @@ class AppDetailsActivity : BaseDetailsActivity() {
updateActionState(State.PROGRESS) updateActionState(State.PROGRESS)
task { task {
val authData = AuthProvider if (app.inPlayStore) {
.with(this) PurchaseHelper(authData)
.getAuthData() .using(HttpClient.getPreferredClient())
.purchase(app.packageName, app.versionCode, app.offerType)
PurchaseHelper(authData) } else {
.using(HttpClient.getPreferredClient()) val metaFile = app.fileList[0]
.purchase(app.packageName, app.versionCode, app.offerType) val fileList: MutableList<File> = mutableListOf()
fileList.add(metaFile)
fileList
}
} successUi { files -> } successUi { files ->
if (files.isNotEmpty()) { if (files.isNotEmpty()) {
var hasOBB = false var hasOBB = false

View File

@@ -45,6 +45,9 @@ abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewM
val liveData: MutableLiveData<ViewState> = MutableLiveData() val liveData: MutableLiveData<ViewState> = MutableLiveData()
var streamBundle: StreamBundle = StreamBundle() var streamBundle: StreamBundle = StreamBundle()
/* Should certainly do it in a better way :(*/
var promotionsAdded: Boolean = false
lateinit var type: StreamHelper.Type lateinit var type: StreamHelper.Type
lateinit var category: StreamHelper.Category lateinit var category: StreamHelper.Category
@@ -72,6 +75,13 @@ abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewM
type type
) )
//Add promotional cluster
if (!promotionsAdded) {
val promotionalCluster = promotionalCluster()
newBundle.streamClusters[promotionalCluster.id] = promotionalCluster
promotionsAdded = true
}
//Update old bundle //Update old bundle
streamBundle.apply { streamBundle.apply {
streamClusters.putAll(newBundle.streamClusters) streamClusters.putAll(newBundle.streamClusters)
@@ -118,4 +128,15 @@ abstract class BaseClusterViewModel(application: Application) : BaseAndroidViewM
clusterNextPageUrl = newCluster.clusterNextPageUrl clusterNextPageUrl = newCluster.clusterNextPageUrl
} }
} }
private fun promotionalCluster(): StreamCluster {
val response = HttpClient.getPreferredClient().get(
"https://promotions.auroraoss.com",
hashMapOf()
)
return if (response.isSuccessful)
gson.fromJson(String(response.responseBytes), StreamCluster::class.java)
else
StreamCluster()
}
} }