Skip to content
Permalink
Browse files

Remove Toolbar from home

Currently on Followed has a Toolbar, the other
screens will follow
  • Loading branch information...
chrisbanes committed Oct 1, 2019
1 parent 5c92ae1 commit 9772e0eaa6f38d773f53e897599a754ae1952299
@@ -39,9 +39,13 @@ open class TiviAppNavigator @Inject constructor(
override fun startShowDetails(id: Long, sharedElements: SharedElementHelper?) {
context.startActivity(ShowDetailsActivity.createIntent(context, id))
}

override fun startLogin() {
throw IllegalArgumentException("This app navigator can't handle login calls")
}
}

internal class TiviAppActivityNavigator(private val activity: Activity) : TiviAppNavigator(activity) {
internal open class TiviAppActivityNavigator(private val activity: Activity) : TiviAppNavigator(activity) {
override fun startShowDetails(id: Long, sharedElements: SharedElementHelper?) {
activity.startActivityForResult(
ShowDetailsActivity.createIntent(activity, id),
@@ -21,36 +21,24 @@ import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.DiffUtil
import app.tivi.R
import app.tivi.TiviActivityMvRxView
import app.tivi.databinding.ActivityHomeBinding
import app.tivi.extensions.beginDelayedTransition
import app.tivi.extensions.doOnApplyWindowInsets
import app.tivi.extensions.hideSoftInput
import app.tivi.home.main.HomeNavigationItemDiffAdapter
import app.tivi.home.main.HomeNavigationItemDiffCallback
import app.tivi.home.search.SearchFragment
import app.tivi.home.search.SearchViewModel
import app.tivi.trakt.TraktAuthState
import app.tivi.trakt.TraktConstants
import app.tivi.util.AppCoroutineDispatchers
import coil.Coil
import coil.api.load
import coil.size.PixelSize
import coil.size.Size
import coil.size.SizeResolver
import coil.transform.CircleCropTransformation
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
@@ -89,27 +77,8 @@ class HomeActivity : TiviActivityMvRxView() {
binding.homeRoot.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

binding.statusScrim.doOnApplyWindowInsets { view, insets, _, _ ->
view.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = insets.systemWindowInsetTop
validate()
}
}

binding.homeToolbar.setOnMenuItemClickListener(::onMenuItemClicked)

val searchMenuItem = binding.homeToolbar.menu.findItem(R.id.home_menu_search)
searchMenuItem.setOnActionExpandListener(SearchViewListeners())

binding.homeToolbar.setupWithNavController(
navController,
AppBarConfiguration.Builder(
R.id.navigation_followed,
R.id.navigation_watched,
R.id.navigation_discover,
R.id.navigation_settings
).build()
)
// val searchMenuItem = binding.homeToolbar.menu.findItem(R.id.home_menu_search)
// searchMenuItem.setOnActionExpandListener(SearchViewListeners())

binding.homeBottomNavigation.setupWithNavController(navController)

@@ -143,28 +112,6 @@ class HomeActivity : TiviActivityMvRxView() {
val result = DiffUtil.calculateDiff(diffCallback, false)
result.dispatchUpdatesTo(
HomeNavigationItemDiffAdapter(state.navigationItems, bottomNavMenu))

val userMenuItem = binding.homeToolbar.menu.findItem(R.id.home_menu_user_avatar)
val loginMenuItem = binding.homeToolbar.menu.findItem(R.id.home_menu_user_login)
if (state.authState == TraktAuthState.LOGGED_IN) {
userMenuItem.isVisible = true
if (state.user?.avatarUrl != null) {
Coil.load(this, state.user.avatarUrl) {
transformations(CircleCropTransformation())
size(object : SizeResolver {
override suspend fun size(): Size {
val height = binding.homeToolbar.height
return PixelSize(height, height)
}
})
target { userMenuItem.icon = it }
}
}
loginMenuItem.isVisible = false
} else if (state.authState == TraktAuthState.LOGGED_OUT) {
userMenuItem.isVisible = false
loginMenuItem.isVisible = true
}
}
}

@@ -178,24 +125,8 @@ class HomeActivity : TiviActivityMvRxView() {
}
}

override fun onBackPressed() {
if (binding.homeToolbar.hasExpandedActionView()) {
binding.homeToolbar.collapseActionView()
return
}
super.onBackPressed()
}

private fun onMenuItemClicked(item: MenuItem) = when (item.itemId) {
R.id.home_menu_user_avatar -> {
viewModel.onProfileItemClicked()
true
}
R.id.home_menu_user_login -> {
viewModel.onLoginItemClicked(authService)
true
}
else -> false
internal fun startLogin() {
viewModel.onLoginItemClicked(authService)
}

private inner class SearchViewListeners : SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
@@ -224,17 +155,13 @@ class HomeActivity : TiviActivityMvRxView() {
val searchView = item.actionView as SearchView
searchView.setOnQueryTextListener(this)

binding.homeToolbar.beginDelayedTransition(100)

// Open the search fragment
navController.navigate(R.id.navigation_search)

return true
}

override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
binding.homeToolbar.beginDelayedTransition(100)

expandedMenuItem = null

val searchView = item.actionView as SearchView
@@ -81,10 +81,6 @@ class HomeActivityViewModel @AssistedInject constructor(
}
}

fun onProfileItemClicked() {
// TODO
}

fun onLoginItemClicked(authService: AuthorizationService) {
traktManager.startAuth(0, authService)
}
@@ -0,0 +1,27 @@
/*
* Copyright 2019 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

import app.tivi.TiviAppActivityNavigator

internal class HomeAppNavigator(
private val activity: HomeActivity
) : TiviAppActivityNavigator(activity) {
override fun startLogin() {
activity.startLogin()
}
}
@@ -18,7 +18,6 @@ package app.tivi.home

import android.content.Context
import app.tivi.AppNavigator
import app.tivi.TiviAppActivityNavigator
import app.tivi.home.discover.DiscoverBuilder
import app.tivi.home.followed.FollowedBuilder
import app.tivi.home.popular.PopularBuilder
@@ -52,9 +51,7 @@ internal abstract class HomeBuilder {
@Module(includes = [HomeModuleBinds::class])
class HomeModule {
@Provides
fun provideAppNavigator(activity: HomeActivity): AppNavigator {
return TiviAppActivityNavigator(activity)
}
fun provideAppNavigator(activity: HomeActivity): AppNavigator = HomeAppNavigator(activity)
}

@Module
@@ -21,9 +21,11 @@ import android.content.SharedPreferences
import android.os.Build
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.coroutineScope
import androidx.navigation.ui.AppBarConfiguration
import androidx.preference.PreferenceManager
import app.tivi.BuildConfig
import app.tivi.TiviApplication
import app.tivi.home.followed.R
import app.tivi.util.AppCoroutineDispatchers
import dagger.Module
import dagger.Provides
@@ -138,4 +140,13 @@ class AppModule {
fun provideLongLifetimeScope(): CoroutineScope {
return ProcessLifecycleOwner.get().lifecycle.coroutineScope
}

@Provides
@Singleton
fun provideAppBarConfiguration() = AppBarConfiguration.Builder(
R.id.navigation_followed,
R.id.navigation_watched,
R.id.navigation_discover,
R.id.navigation_settings
).build()
}
@@ -27,23 +27,6 @@
app:paddingRightSystemWindowInsets="@{true}"
tools:context=".home.HomeActivity">

<!-- The height of this is updated via an OnApplyWindowInsetsListener -->
<View
android:id="@+id/status_scrim"
android:layout_width="0dp"
android:layout_height="1px"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.Toolbar
android:id="@+id/home_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.MaterialComponents.ActionBar"
app:layout_constraintTop_toBottomOf="@id/status_scrim"
app:menu="@menu/home_toolbar" />

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/home_bottom_navigation"
android:layout_width="0dp"
@@ -62,7 +45,7 @@
app:layout_constraintBottom_toTopOf="@id/home_bottom_navigation"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/home_toolbar"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
@@ -21,4 +21,5 @@ import android.app.PendingIntent
interface AppNavigator {
fun provideAuthHandleResponseIntent(requestCode: Int): PendingIntent
fun startShowDetails(id: Long, sharedElements: SharedElementHelper?)
fun startLogin()
}
@@ -0,0 +1,42 @@
/*
* Copyright 2019 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.common.imageloading

import android.content.Context
import android.view.MenuItem
import app.tivi.extensions.resolveThemeDimensionPixelSize
import coil.Coil
import coil.api.load
import coil.size.PixelSize
import coil.size.Size
import coil.size.SizeResolver
import coil.transform.CircleCropTransformation

fun MenuItem.loadImageUrl(context: Context, url: String, circleCrop: Boolean = true) {
Coil.load(context, url) {
if (circleCrop) {
transformations(CircleCropTransformation())
}
size(object : SizeResolver {
override suspend fun size(): Size {
val height = context.resolveThemeDimensionPixelSize(android.R.attr.actionBarSize)
return PixelSize(height, height)
}
})
target { icon = it }
}
}
@@ -21,6 +21,7 @@ import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import androidx.annotation.AttrRes
import androidx.core.content.res.getDimensionPixelSizeOrThrow
import androidx.core.content.res.getResourceIdOrThrow
import androidx.core.content.res.use

@@ -43,4 +44,11 @@ fun Context.resolveThemeReferenceResId(@AttrRes resId: Int): Int {
return obtainStyledAttributes(intArrayOf(resId)).use {
it.getResourceIdOrThrow(0)
}
}

@SuppressLint("Recycle")
fun Context.resolveThemeDimensionPixelSize(@AttrRes resId: Int): Int {
return obtainStyledAttributes(intArrayOf(resId)).use {
it.getDimensionPixelSizeOrThrow(0)
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2019 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.ui

import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import app.tivi.data.entities.TraktUser
import app.tivi.trakt.TraktAuthState

class AuthStateMenuItemBinder(
private val userMenuItem: MenuItem,
private val loginMenuItem: MenuItem,
private val loadImageFunc: (MenuItem, url: String) -> Unit
) {
fun bind(authState: TraktAuthState, user: TraktUser? = null) {
if (authState == TraktAuthState.LOGGED_IN) {
userMenuItem.isVisible = true
user?.avatarUrl?.also { url -> loadImageFunc(userMenuItem, url) }
loginMenuItem.isVisible = false
} else if (authState == TraktAuthState.LOGGED_OUT) {
userMenuItem.isVisible = false
loginMenuItem.isVisible = true
}
}
}

fun authStateToolbarMenuBinder(
toolbar: Toolbar,
userMenuItemId: Int,
loginMenuItemId: Int,
loadImageFunc: (MenuItem, url: String) -> Unit
) = AuthStateMenuItemBinder(
toolbar.menu.findItem(userMenuItemId),
toolbar.menu.findItem(loginMenuItemId),
loadImageFunc
)

0 comments on commit 9772e0e

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