Skip to content
Permalink
Browse files

Add recommended entry grid fragment

  • Loading branch information...
chrisbanes committed Aug 16, 2019
1 parent e57d7d3 commit a3dc7f5ed6db294f838abece7a62c2d9b18c5c9b
@@ -30,6 +30,7 @@
<option value="$PROJECT_DIR$/ui-episodedetails" />
<option value="$PROJECT_DIR$/ui-followed" />
<option value="$PROJECT_DIR$/ui-popular" />
<option value="$PROJECT_DIR$/ui-recommended" />
<option value="$PROJECT_DIR$/ui-showdetails" />
<option value="$PROJECT_DIR$/ui-trending" />
<option value="$PROJECT_DIR$/ui-watched" />
@@ -24,6 +24,7 @@
<module fileurl="file://$PROJECT_DIR$/ui-episodedetails/ui-episodedetails.iml" filepath="$PROJECT_DIR$/ui-episodedetails/ui-episodedetails.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-followed/ui-followed.iml" filepath="$PROJECT_DIR$/ui-followed/ui-followed.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-popular/ui-popular.iml" filepath="$PROJECT_DIR$/ui-popular/ui-popular.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-recommended/ui-recommended.iml" filepath="$PROJECT_DIR$/ui-recommended/ui-recommended.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-showdetails/ui-showdetails.iml" filepath="$PROJECT_DIR$/ui-showdetails/ui-showdetails.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-trending/ui-trending.iml" filepath="$PROJECT_DIR$/ui-trending/ui-trending.iml" />
<module fileurl="file://$PROJECT_DIR$/ui-watched/ui-watched.iml" filepath="$PROJECT_DIR$/ui-watched/ui-watched.iml" />
@@ -182,6 +182,7 @@ dependencies {
implementation project(":ui-watched")
implementation project(":ui-popular")
implementation project(":ui-trending")
implementation project(":ui-recommended")

implementation Libs.AndroidX.Lifecycle.extensions
implementation Libs.AndroidX.Lifecycle.viewmodel
@@ -22,6 +22,7 @@ import app.tivi.TiviAppActivityNavigator
import app.tivi.home.discover.DiscoverBuilder
import app.tivi.home.followed.FollowedBuilder
import app.tivi.home.popular.PopularBuilder
import app.tivi.home.recommended.RecommendedBuilder
import app.tivi.home.search.SearchBuilder
import app.tivi.home.trending.TrendingBuilder
import app.tivi.home.watched.WatchedBuilder
@@ -42,7 +43,8 @@ internal abstract class HomeBuilder {
TrendingBuilder::class,
PopularBuilder::class,
WatchedBuilder::class,
FollowedBuilder::class
FollowedBuilder::class,
RecommendedBuilder::class
])
internal abstract fun homeActivity(): HomeActivity
}
@@ -45,6 +45,11 @@
android:name="app.tivi.home.popular.PopularShowsFragment"
android:label="@string/discover_popular" />

<fragment
android:id="@id/navigation_recommended"
android:name="app.tivi.home.recommended.RecommendedShowsFragment"
android:label="@string/discover_recommended" />

<fragment
android:id="@id/navigation_watched"
android:name="app.tivi.home.watched.WatchedFragment"
@@ -23,6 +23,7 @@
<id name="navigation_popular" />
<id name="navigation_followed" />
<id name="navigation_watched" />
<id name="navigation_recommended" />

<id name="activity_show_details" />

@@ -37,4 +37,5 @@ include ':ui-followed'
include ':ui-watched'
include ':ui-trending'
include ':ui-popular'
include ':ui-recommended'
include ':app'
@@ -94,7 +94,13 @@ class DiscoverFragment : TiviMvRxFragment() {
}

override fun onRecommendedHeaderClicked(items: List<RecommendedEntryWithShow>) {
// TODO
val extras = listItemSharedElementHelper.createForItems(items)

findNavController().navigate(
R.id.navigation_recommended,
null,
null,
extras.toFragmentNavigatorExtras())
}

override fun onItemClicked(viewHolderId: Long, item: EntryWithShow<out Entry>) {
@@ -0,0 +1,95 @@
/*
* Copyright 2018 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import app.tivi.buildsrc.Libs

apply plugin: 'com.android.library'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-kapt'
kapt {
correctErrorTypes = true
useBuildCache = true
}

apply plugin: 'kotlin-android-extensions'
androidExtensions {
experimental = true
}

android {
compileSdkVersion buildConfig.compileSdk

defaultConfig {
minSdkVersion buildConfig.minSdk
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation project(":base")
implementation project(":base-android")
implementation project(':domain')
implementation project(":common-ui")
implementation project(":common-epoxy")
implementation project(":common-layouts")
implementation project(":common-glide")
implementation project(":common-databinding")
implementation project(":common-entrygrid")

implementation Libs.AndroidX.Lifecycle.extensions
implementation Libs.AndroidX.Lifecycle.viewmodel
kapt Libs.AndroidX.Lifecycle.compiler

implementation Libs.AndroidX.Paging.runtime

implementation Libs.AndroidX.appcompat
implementation Libs.AndroidX.browser
implementation Libs.AndroidX.palette
implementation Libs.AndroidX.recyclerview
implementation Libs.AndroidX.emoji
implementation Libs.AndroidX.preference
implementation Libs.AndroidX.constraintlayout
implementation Libs.AndroidX.coreKtx
implementation Libs.AndroidX.Fragment.fragment
implementation Libs.AndroidX.Fragment.fragmentKtx
implementation Libs.AndroidX.Navigation.fragment
implementation Libs.AndroidX.Navigation.ui

implementation Libs.Google.material

implementation Libs.Kotlin.stdlib
implementation Libs.Kotlin.reflect

implementation Libs.Dagger.androidSupport
kapt Libs.Dagger.compiler
kapt Libs.Dagger.androidProcessor

implementation Libs.mvRx

implementation Libs.Epoxy.epoxy
implementation Libs.Epoxy.paging
implementation Libs.Epoxy.dataBinding
kapt Libs.Epoxy.processor

implementation Libs.gravitySnapHelper
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2018 Google, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.tivi.home.recommended">

</manifest>
@@ -0,0 +1,35 @@
/*
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package app.tivi.home.recommended

import androidx.lifecycle.ViewModel
import app.tivi.inject.ViewModelKey
import dagger.Binds
import dagger.Module
import dagger.android.ContributesAndroidInjector
import dagger.multibindings.IntoMap

@Module
abstract class RecommendedBuilder {
@ContributesAndroidInjector
internal abstract fun RecommendedShowsFragment(): RecommendedShowsFragment

@Binds
@IntoMap
@ViewModelKey(RecommendedShowsViewModel::class)
abstract fun bindRecommendedShowsViewModel(viewModel: RecommendedShowsViewModel): ViewModel
}
@@ -0,0 +1,65 @@
/*
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package app.tivi.home.recommended

import android.view.View
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import app.tivi.SharedElementHelper
import app.tivi.common.layouts.PosterGridItemBindingModel_
import app.tivi.data.entities.findHighestRatedPoster
import app.tivi.data.resultentities.RecommendedEntryWithShow
import app.tivi.extensions.toActivityNavigatorExtras
import app.tivi.util.EntryGridEpoxyController
import app.tivi.util.EntryGridFragment
import com.airbnb.epoxy.EpoxyModel
import javax.inject.Inject

class RecommendedShowsFragment : EntryGridFragment<RecommendedEntryWithShow, RecommendedShowsViewModel>() {
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
override val viewModel: RecommendedShowsViewModel by viewModels(factoryProducer = { viewModelFactory })

override fun createController(): EntryGridEpoxyController<RecommendedEntryWithShow> {
return object : EntryGridEpoxyController<RecommendedEntryWithShow>(R.string.discover_recommended) {
override fun buildItemModel(item: RecommendedEntryWithShow): EpoxyModel<*> {
return PosterGridItemBindingModel_()
.id(item.generateStableId())
.tmdbImageUrlProvider(tmdbImageUrlProvider)
.posterImage(item.images.findHighestRatedPoster())
.tiviShow(item.show)
.transitionName(item.show.homepage)
.clickListener(View.OnClickListener { onItemClicked(item) })
}
}
}

internal fun onItemClicked(item: RecommendedEntryWithShow) {
val sharedElements = SharedElementHelper()
binding.gridRecyclerview.findViewHolderForItemId(item.generateStableId())?.let {
sharedElements.addSharedElement(it.itemView, "poster")
}

findNavController().navigate(
R.id.activity_show_details,
bundleOf("show_id" to item.show.id),
null,
sharedElements.toActivityNavigatorExtras(requireActivity())
)
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package app.tivi.home.recommended

import app.tivi.data.resultentities.RecommendedEntryWithShow
import app.tivi.domain.interactors.UpdateRecommendedShows
import app.tivi.domain.interactors.UpdateRecommendedShows.Page.NEXT_PAGE
import app.tivi.domain.interactors.UpdateRecommendedShows.Page.REFRESH
import app.tivi.domain.observers.ObservePagedRecommendedShows
import app.tivi.tmdb.TmdbManager
import app.tivi.util.AppCoroutineDispatchers
import app.tivi.util.EntryViewModel
import app.tivi.util.Logger
import javax.inject.Inject

class RecommendedShowsViewModel @Inject constructor(
override val dispatchers: AppCoroutineDispatchers,
override val pagingInteractor: ObservePagedRecommendedShows,
private val interactor: UpdateRecommendedShows,
override val tmdbManager: TmdbManager,
override val logger: Logger
) : EntryViewModel<RecommendedEntryWithShow, ObservePagedRecommendedShows>() {
init {
pagingInteractor(ObservePagedRecommendedShows.Params(pageListConfig, boundaryCallback))

refresh(false)
}

override fun callLoadMore() = interactor(UpdateRecommendedShows.Params(NEXT_PAGE, true))

override fun callRefresh(fromUser: Boolean) = interactor(UpdateRecommendedShows.Params(REFRESH, fromUser))
}

0 comments on commit a3dc7f5

Please sign in to comment.
You can’t perform that action at this time.