mikepenz / FastAdapter

The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...
https://mikepenz.dev
Apache License 2.0
3.83k stars 492 forks source link

Setting a Snackbar using UndoHelper's withSnackbar does nothing. #1019

Closed daniyelp closed 2 years ago

daniyelp commented 2 years ago

About this issue

As the title says, if I use withSnackbar method of UndoHelper and then I call remove passing just the positions, nothing happens. The Snackbar doesn't show up.

How to recreate the issue

In the sample app, inside MultiselectSampleActivity, change mUndoHelper to

mUndoHelper = UndoHelper(mFastAdapter, object : UndoHelper.UndoListener<SimpleItem> {
    override fun commitRemove(positions: Set<Int>, removed: ArrayList<FastAdapter.RelativeInfo<SimpleItem>>) {
        Log.e("UndoHelper", "Positions: " + positions.toString() + " Removed: " + removed.size)
    }
}).apply { withSnackBar(Snackbar.make(findViewById(android.R.id.content), "Item removed", Snackbar.LENGTH_LONG), "Undo") }

Then further down replace

mUndoHelper.remove(findViewById(android.R.id.content), "Item removed", "Undo", Snackbar.LENGTH_LONG, selectExtension.selections)

with

mUndoHelper.remove(selectExtension.selections)

Details

I'd say that I identified the issue. Inside UndoHelper, when creating a new Snackbar :

fun remove(positions: Set<Int>): Snackbar? {
        val snackBar = this.snackBar ?: return null
        val snackBarView = snackBar.view
        val snackBarText = snackBarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView
        return remove(snackBarView, snackBarText.text.toString(), snackBarActionText, snackBar.duration, positions)
    }

In here, snackbar.view is wil not be the same as the view that you are passing inside Snackbar.make(view, ..., ...). I see that we don't want to use the instance that was passed using withSnackbar method. Instead of trying to clone the Snackbar, we could pass in withSnackbar method a lambda that creates a Snackbar:

withSnackbar(actionText) { Snackbar.make(...) }

and use that lambda inside the remove method.

I would have made a PR but mabye there is a better way.