More snack

This commit is contained in:
Jay 2019-10-30 01:19:30 -07:00
parent 1d0f6e8bce
commit d719cae942
11 changed files with 110 additions and 31 deletions

View File

@ -79,14 +79,12 @@ class CoverCache(private val context: Context) {
// Check if url is empty. // Check if url is empty.
if (thumbnailUrl.isNullOrEmpty()) return if (thumbnailUrl.isNullOrEmpty()) return
launchUI { launchUI {
if (delayBy > 0) { delay(delayBy)
delay(delayBy) if (!manga.favorite) {
if (manga.favorite) cancel() // Remove file.
val file = getCoverFile(thumbnailUrl)
if (file.exists()) file.delete()
} }
// Remove file.
val file = getCoverFile(thumbnailUrl)
if (file.exists())
file.delete()
} }
} }

View File

@ -516,7 +516,7 @@ open class BrowseCatalogueController(bundle: Bundle) :
} else { } else {
addManga(manga, position) addManga(manga, position)
snack = snack =
catalogue_view?.snack(activity.getString(R.string.manga_added_library), Snackbar.LENGTH_SHORT) catalogue_view?.snack(activity.getString(R.string.manga_added_library))
} }
} }

View File

@ -95,7 +95,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
swipe_refresh.setOnRefreshListener { swipe_refresh.setOnRefreshListener {
if (!LibraryUpdateService.isRunning(context)) { if (!LibraryUpdateService.isRunning(context)) {
LibraryUpdateService.start(context, category) LibraryUpdateService.start(context, category)
context.toast(R.string.updating_category) swipe_refresh.snack(R.string.updating_category)
} }
// It can be a very long operation, so we disable swipe refresh and show a toast. // It can be a very long operation, so we disable swipe refresh and show a toast.
swipe_refresh.isRefreshing = false swipe_refresh.isRefreshing = false

View File

@ -157,13 +157,6 @@ class LibraryController(
if (selectedMangas.isNotEmpty()) { if (selectedMangas.isNotEmpty()) {
createActionModeIfNeeded() createActionModeIfNeeded()
} }
view.doOnApplyWindowInsets { view, insets, psdding ->
val contextView = activity?.window?.decorView?.findViewById<View>(R.id.action_mode_bar)
if (Build.VERSION.SDK_INT >= 23) contextView?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
leftMargin = view.rootWindowInsets.systemWindowInsetLeft
rightMargin = view.rootWindowInsets.systemWindowInsetRight
}
}
} }
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {

View File

@ -44,6 +44,7 @@ import eu.kanade.tachiyomi.util.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.marginBottom import eu.kanade.tachiyomi.util.marginBottom
import eu.kanade.tachiyomi.util.marginTop import eu.kanade.tachiyomi.util.marginTop
import eu.kanade.tachiyomi.util.openInBrowser import eu.kanade.tachiyomi.util.openInBrowser
import eu.kanade.tachiyomi.util.updateLayoutParams
import eu.kanade.tachiyomi.util.updatePadding import eu.kanade.tachiyomi.util.updatePadding
import eu.kanade.tachiyomi.util.updatePaddingRelative import eu.kanade.tachiyomi.util.updatePaddingRelative
import kotlinx.android.synthetic.main.chapters_controller.view.* import kotlinx.android.synthetic.main.chapters_controller.view.*
@ -153,7 +154,11 @@ class MainActivity : BaseActivity() {
val drawerContainer: FrameLayout = findViewById(R.id.drawer_container) val drawerContainer: FrameLayout = findViewById(R.id.drawer_container)
drawerContainer.setOnApplyWindowInsetsListener { v, insets -> drawerContainer.setOnApplyWindowInsetsListener { v, insets ->
val contextView = window?.decorView?.findViewById<View>(R.id.action_mode_bar)
contextView?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
leftMargin = insets.systemWindowInsetLeft
rightMargin = insets.systemWindowInsetRight
}
// Consume any horizontal insets and pad all content in. There's not much we can do // Consume any horizontal insets and pad all content in. There's not much we can do
// with horizontal insets // with horizontal insets
v.updatePadding( v.updatePadding(

View File

@ -5,12 +5,15 @@ import android.animation.AnimatorListenerAdapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Build
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.view.* import android.view.*
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.jakewharton.rxbinding.support.v4.widget.refreshes import com.jakewharton.rxbinding.support.v4.widget.refreshes
import com.jakewharton.rxbinding.view.clicks import com.jakewharton.rxbinding.view.clicks
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -26,6 +29,11 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.* import eu.kanade.tachiyomi.util.*
import kotlinx.android.synthetic.main.chapters_controller.* import kotlinx.android.synthetic.main.chapters_controller.*
import timber.log.Timber import timber.log.Timber
import com.google.android.material.floatingactionbutton.FloatingActionButton
import android.content.Context
import android.util.AttributeSet
import androidx.core.view.ViewCompat
import kotlin.math.*
class ChaptersController : NucleusController<ChaptersPresenter>(), class ChaptersController : NucleusController<ChaptersPresenter>(),
ActionMode.Callback, ActionMode.Callback,
@ -48,6 +56,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
*/ */
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private var snack:Snackbar? = null
/** /**
* Selected items. Used to restore selections after a rotation. * Selected items. Used to restore selections after a rotation.
*/ */
@ -83,6 +92,11 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
val fabBaseMarginBottom = fab?.marginBottom ?: 0 val fabBaseMarginBottom = fab?.marginBottom ?: 0
recycler.doOnApplyWindowInsets { v, insets, padding -> recycler.doOnApplyWindowInsets { v, insets, padding ->
v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom) v.updatePaddingRelative(bottom = padding.bottom + insets.systemWindowInsetBottom)
//if (snack == null) {
//fab?.translationY = -insets.systemWindowInsetBottom.toFloat()
/*}
else
fab?.translationY = 0f*/
fab?.updateLayoutParams<ViewGroup.MarginLayoutParams> { fab?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = fabBaseMarginBottom + insets.systemWindowInsetBottom bottomMargin = fabBaseMarginBottom + insets.systemWindowInsetBottom
} }
@ -108,7 +122,14 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
openChapter(item.chapter) openChapter(item.chapter)
} }
} else { } else {
view.context.toast(R.string.no_next_chapter) snack = view.snack(R.string.no_next_chapter, Snackbar.LENGTH_LONG) {
addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
super.onDismissed(transientBottomBar, event)
if (snack == transientBottomBar) snack = null
}
})
}
} }
} }
} }
@ -373,11 +394,17 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
presenter.downloadChapters(chapters) presenter.downloadChapters(chapters)
if (view != null && !presenter.manga.favorite) { if (view != null && !presenter.manga.favorite) {
val snack = view.snack(view.context.getString(R.string.snack_add_to_library), Snackbar snack = view.snack(view.context.getString(R.string.snack_add_to_library), Snackbar
.LENGTH_INDEFINITE) { .LENGTH_INDEFINITE) {
setAction(R.string.action_add) { setAction(R.string.action_add) {
presenter.addToLibrary() presenter.addToLibrary()
} }
addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
super.onDismissed(transientBottomBar, event)
if (snack == transientBottomBar) snack = null
}
})
} }
} }
} }
@ -493,3 +520,7 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
} }
} }
} }
class ShrinkBehavior(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<FloatingActionButton>(context, attrs) {
}

View File

@ -421,7 +421,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
private fun showAddedSnack() { private fun showAddedSnack() {
val view = container val view = container
snack?.dismiss() snack?.dismiss()
snack = view?.snack(view.context.getString(R.string.manga_added_library), Snackbar.LENGTH_SHORT) snack = view?.snack(view.context.getString(R.string.manga_added_library))
} }
private fun showRemovedSnack() { private fun showRemovedSnack() {

View File

@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.RecyclerWindowInsetsListener import eu.kanade.tachiyomi.util.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.snack
import eu.kanade.tachiyomi.util.toast import eu.kanade.tachiyomi.util.toast
import kotlinx.android.synthetic.main.recent_chapters_controller.* import kotlinx.android.synthetic.main.recent_chapters_controller.*
import timber.log.Timber import timber.log.Timber
@ -86,9 +87,9 @@ class RecentChaptersController : NucleusController<RecentChaptersPresenter>(),
swipe_refresh.refreshes().subscribeUntilDestroy { swipe_refresh.refreshes().subscribeUntilDestroy {
if (!LibraryUpdateService.isRunning(view.context)) { if (!LibraryUpdateService.isRunning(view.context)) {
LibraryUpdateService.start(view.context) LibraryUpdateService.start(view.context)
view.context.toast(R.string.action_update_library) view.snack(R.string.action_update_library)
} }
// It can be a very long operation, so we disable swipe refresh and show a toast. // It can be a very long operation, so we disable swipe refresh and show a snackbar.
swipe_refresh.isRefreshing = false swipe_refresh.isRefreshing = false
} }
recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener) recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)

View File

@ -17,6 +17,7 @@ import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowInsets import android.view.WindowInsets
import android.widget.TextView import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.amulyakhare.textdrawable.util.ColorGenerator import com.amulyakhare.textdrawable.util.ColorGenerator
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -36,28 +37,45 @@ fun View.getCoordinates() = Point((left + right) / 2, (top + bottom) / 2)
* @param length the duration of the snack. * @param length the duration of the snack.
* @param f a function to execute in the snack, allowing for example to define a custom action. * @param f a function to execute in the snack, allowing for example to define a custom action.
*/ */
fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG, f: (Snackbar.() -> fun View.snack(message: String, length: Int = Snackbar.LENGTH_SHORT, f: (Snackbar.() ->
Unit)? = null): Snackbar { Unit)? = null): Snackbar {
val snack = Snackbar.make(this, message, length) val snack = Snackbar.make(this, message, length)
val textView: TextView = snack.view.findViewById(com.google.android.material.R.id.snackbar_text) val textView: TextView = snack.view.findViewById(com.google.android.material.R.id.snackbar_text)
textView.setTextColor(context.getResourceColor(android.R.attr.textColorPrimaryInverse)) textView.setTextColor(context.getResourceColor(android.R.attr.textColorPrimaryInverse))
when { when {
Build.VERSION.SDK_INT >= 23 -> snack.config(context, rootWindowInsets.systemWindowInsetBottom) Build.VERSION.SDK_INT >= 23 -> {
val leftM = if (this is CoordinatorLayout) 0 else rootWindowInsets.systemWindowInsetLeft
val rightM = if (this is CoordinatorLayout) 0
else rootWindowInsets.systemWindowInsetRight
snack.config(context, rootWindowInsets
.systemWindowInsetBottom, rightM, leftM)
}
else -> snack.config(context) else -> snack.config(context)
} }
if (f != null) { if (f != null) {
snack.f() snack.f()
} }
snack.view.doOnApplyWindowInsets { v, _, padding -> snack.view.doOnApplyWindowInsets { v, insets, padding ->
v.setPadding(padding.left,0,padding.right,0) //v.setPadding(padding.left, 0, padding.right, 0)
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (Build.VERSION.SDK_INT < 23) {
bottomMargin = 12 + insets.systemWindowInsetBottom
}
}
} }
snack.show() snack.show()
return snack return snack
} }
fun Snackbar.config(context: Context, bottomMargin: Int = 0) { fun View.snack(resource: Int, length: Int = Snackbar.LENGTH_SHORT, f: (Snackbar.() ->
Unit)? = null): Snackbar {
return snack(context.getString(resource), length, f)
}
fun Snackbar.config(context: Context, bottomMargin: Int = 0, rightMargin: Int = 0, leftMargin:
Int = 0) {
val params = this.view.layoutParams as ViewGroup.MarginLayoutParams val params = this.view.layoutParams as ViewGroup.MarginLayoutParams
params.setMargins(12, 12, 12, 12 + bottomMargin) params.setMargins(12 + leftMargin, 12, 12 + rightMargin, 12 + bottomMargin)
this.view.layoutParams = params this.view.layoutParams = params
this.view.background = context.getDrawable(R.drawable.bg_snackbar) this.view.background = context.getDrawable(R.drawable.bg_snackbar)

View File

@ -7,10 +7,14 @@ import android.util.AttributeSet
import android.view.View import android.view.View
import android.view.animation.Animation import android.view.animation.Animation
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.snackbar.Snackbar
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlin.math.min
@Suppress("unused", "UNUSED_PARAMETER") @Suppress("unused", "UNUSED_PARAMETER")
class FABAnimationUpDown @JvmOverloads constructor(ctx: Context, attrs: AttributeSet? = null) : FABAnimationBase() { class FABAnimationUpDown @JvmOverloads constructor(ctx: Context, attrs: AttributeSet? = null) :
FABAnimationBase() {
private val INTERPOLATOR = FastOutSlowInInterpolator() private val INTERPOLATOR = FastOutSlowInInterpolator()
@ -48,4 +52,31 @@ class FABAnimationUpDown @JvmOverloads constructor(ctx: Context, attrs: Attribut
button.visibility = View.VISIBLE button.visibility = View.VISIBLE
button.startAnimation(inAnimation) button.startAnimation(inAnimation)
} }
override fun layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View): Boolean {
return dependency is Snackbar.SnackbarLayout
}
override fun onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View): Boolean {
val translationY = getFabTranslationYForSnackbar(parent, child)
val percentComplete = -translationY / dependency.height
val scaleFactor = 1 - percentComplete
child.translationY = -translationY
return false
}
private fun getFabTranslationYForSnackbar(parent: CoordinatorLayout, fab:
FloatingActionButton): Float {
var minOffset = 0f
val dependencies = parent.getDependencies(fab)
for (i in 0 until dependencies.size) {
val view = dependencies[i]
if (view is Snackbar.SnackbarLayout) {
minOffset = min(minOffset, view.translationY - view.height)
}
}
return minOffset
}
} }

View File

@ -5,6 +5,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"> android:orientation="vertical">
<eu.kanade.tachiyomi.widget.RevealAnimationView <eu.kanade.tachiyomi.widget.RevealAnimationView
@ -12,6 +13,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorAccent" android:background="?attr/colorAccent"
android:clipToPadding="false"
android:elevation="5dp" android:elevation="5dp"
android:visibility="invisible"/> android:visibility="invisible"/>
@ -20,6 +22,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@+id/toolbar_bottom" android:layout_above="@+id/toolbar_bottom"
android:clipToPadding="false"
android:orientation="vertical"> android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -37,8 +40,6 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<eu.davidea.fastscroller.FastScroller <eu.davidea.fastscroller.FastScroller
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fast_scroller" android:id="@+id/fast_scroller"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -51,6 +52,7 @@
android:id="@+id/fab" android:id="@+id/fab"
style="@style/Theme.Widget.FAB" style="@style/Theme.Widget.FAB"
app:layout_anchor="@id/recycler" app:layout_anchor="@id/recycler"
app:layout_anchorGravity="bottom|right|end"
app:srcCompat="@drawable/ic_play_arrow_white_24dp"/> app:srcCompat="@drawable/ic_play_arrow_white_24dp"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>