Skip to content

Instantly share code, notes, and snippets.

@erkattak
Last active August 16, 2018 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erkattak/7741a4e201c6366cf34d17bec0c87911 to your computer and use it in GitHub Desktop.
Save erkattak/7741a4e201c6366cf34d17bec0c87911 to your computer and use it in GitHub Desktop.
package com.oddnetworks.oddnexttv.ui
import android.accounts.Account
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import androidx.leanback.app.BackgroundManager
import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.*
import androidx.core.content.ContextCompat
import com.oddnetworks.oddnexttv.BuildConfig
import com.oddnetworks.oddnexttv.R
import com.oddnetworks.oddnexttv.lib.Constants
import com.oddnetworks.oddnexttv.lib.Utils
import com.oddnetworks.oddnexttv.presenters.CardPresenter
import com.oddnetworks.oddnexttv.presenters.SideInfoCardPresenter
import io.oddworks.device.model.OddCollection
import io.oddworks.device.model.OddVideo
import io.oddworks.device.model.OddView
import io.oddworks.device.model.common.OddResource
import io.oddworks.device.model.common.OddResourceType
import io.oddworks.device.request.OddRequest
import io.oddworks.device.request.RxOddCall
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
const val LARGE_CARD_WIDTH = 659
const val LARGE_CARD_HEIGHT = 371
class MainFragment : BrowseSupportFragment() {
private lateinit var rowsAdapter : ArrayObjectAdapter
private var backgroundManager: BackgroundManager? = null
private var defaultBackground: Drawable? = null
private val account : Account?
get() {
return (activity as ActivityBase).account
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
prepareBackgroundManager()
loadUIElements()
loadData()
setEventListeners()
rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
adapter = rowsAdapter
// don't run entrance transition if fragment is restored.
if (savedInstanceState == null) {
prepareEntranceTransition()
}
}
override fun onResume() {
super.onResume()
backgroundManager?.drawable = defaultBackground
}
private fun prepareBackgroundManager() {
backgroundManager = BackgroundManager.getInstance(activity)
backgroundManager?.attach(requireActivity().window)
defaultBackground = resources.getDrawable(R.drawable.background, null)
backgroundManager?.drawable = defaultBackground
}
// Load the BrowserFragment UI elements
private fun loadUIElements() {
headersState = HEADERS_DISABLED
isHeadersTransitionOnBackEnabled = true
badgeDrawable = ContextCompat.getDrawable(requireActivity(), R.drawable.logo)
searchAffordanceColors = SearchOrbView.Colors(
ContextCompat.getColor(requireActivity(), R.color.colorPrimaryDark),
ContextCompat.getColor(requireActivity(), R.color.colorPrimary))
}
private fun loadData() {
val oddResourceId = requireActivity().intent.getStringExtra(Constants.INTENT_RESOURCE_ID)
val viewObservable = fetchOddView(oddResourceId)
val mainCollectionsObservable = viewObservable.flatMap { oddView ->
Observable.zip<List<OddCollection>>(fetchMainCollectionEntities(oddView)) { collectionResources ->
collectionResources.map {
it as OddCollection
}
}
}.defaultIfEmpty(emptyList())
viewObservable.zipWith(mainCollectionsObservable) {oddView, collections -> Pair(oddView, collections)}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ (oddView, collections) ->
loadRows(oddView, collections)
}, {
// TODO - handle error?
Timber.w("we should definitely handle this error", it)
})
}
private fun fetchOddView(id: String) : Observable<OddView> {
return RxOddCall.observableFrom<OddView> {
OddRequest.Builder(requireContext(), OddResourceType.VIEW)
.resourceId(id)
.account(account)
.include(Constants.MAIN_VIEW_RELATIONSHIP_INCLUDE)
.build()
.enqueueRequest(it)
}
}
private fun fetchMainCollectionEntities(oddView: OddView) : List<Observable<OddCollection>> {
val mainItems = oddView.getIncludedByRelationship(Constants.MAIN_VIEW_RELATIONSHIP_MAIN)
return mainItems
.filter {
it.type == OddResourceType.COLLECTION
}
.map { subCollection ->
RxOddCall.observableFrom<OddCollection> { callback ->
OddRequest.Builder(requireContext(), OddResourceType.COLLECTION)
.resourceId(subCollection.id)
.account(account)
.include("${OddCollection.RELATIONSHIPS.FEATURED},${OddCollection.RELATIONSHIPS.ENTITIES}")
.build()
.enqueueRequest(callback)
}
}
}
private fun loadRows(oddView: OddView, hydratedCollections: List<OddCollection>) {
val rows = mutableListOf<ListRow>()
// Resources in the "featured" relationship will be displayed in a
// single row at the top of the screen. The cards in that row will
// be larger than the resources in subsequent rows.
val featuredResources = oddView.getIncludedByRelationship(Constants.MAIN_VIEW_RELATIONSHIP_FEATURED)
if (featuredResources.count() > 0) {
// use a CardPresenter that's larger
val featuredListRowAdapter = ArrayObjectAdapter(CardPresenter(LARGE_CARD_WIDTH, LARGE_CARD_HEIGHT))
val featuredListRow = ListRow(1, null, featuredListRowAdapter)
featuredListRowAdapter.setItems(featuredResources.toList(), object: DiffCallback<ListRow>() {
override fun areItemsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
return oldItem == newItem
}
})
rows.add(featuredListRow)
}
val mainResources = oddView.getIncludedByRelationship(Constants.MAIN_VIEW_RELATIONSHIP_MAIN)
mainResources.forEachIndexed{ idx, resource ->
if (resource is OddCollection) {
val collection = hydratedCollections.find {
it.id == resource.id
}
if (collection != null) {
val listRow = mapResourceToRow(idx + 1L, collection)
listRow?.let { rows.add(it) }
}
} else {
val listRow = mapResourceToRow(idx + 1L, resource)
listRow?.let { rows.add(it) }
}
}
rowsAdapter.setItems(rows, object: DiffCallback<ListRow>() {
override fun areItemsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
return oldItem == newItem
}
})
startEntranceTransition()
}
private fun mapResourceToRow(index: Long, oddResource: OddResource): ListRow? {
val listRow: ListRow?
val listRowAdapter = ArrayObjectAdapter(CardPresenter())
val videoRowAdapter = ArrayObjectAdapter(SideInfoCardPresenter(requireContext()))
when (oddResource) {
is OddVideo -> {
val resources = Utils.newList(oddResource, "")
val header = null
resources.forEach {
videoRowAdapter.add(it)
}
listRow = ListRow(index, header, videoRowAdapter)
}
is OddCollection -> {
val resources = Utils.newList(oddResource, Constants.COLLECTION_RELATIONSHIP_ENTITIES)
val header = HeaderItem(oddResource.title)
resources.forEach {
listRowAdapter.add(it)
}
listRow = ListRow(index, header, listRowAdapter)
}
else -> listRow = null
}
return listRow
}
private fun setEventListeners() {
if (BuildConfig.ENABLE_SEARCH) {
setOnSearchClickedListener {
val intent = Intent(activity, SearchActivity::class.java)
startActivity(intent)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment