-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
fix: keep deck selection dialog open for multi-select in widget config #20351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,7 @@ import java.util.Locale | |
| open class DeckSelectionDialog : AnalyticsDialogFragment() { | ||
| private lateinit var binding: DialogDeckPickerBinding | ||
| private var dialog: AlertDialog? = null | ||
| private lateinit var decksAdapter: DecksArrayAdapter | ||
| private lateinit var expandImage: Drawable | ||
| private lateinit var collapseImage: Drawable | ||
| private lateinit var decksRoot: DeckNode | ||
|
|
@@ -113,9 +114,9 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |
| val dividerItemDecoration = DividerItemDecoration(binding.list.context, DividerItemDecoration.VERTICAL) | ||
| binding.list.addItemDecoration(dividerItemDecoration) | ||
| val decks: List<SelectableDeck> = getDeckNames(arguments) | ||
| val adapter = DecksArrayAdapter(decks) | ||
| binding.list.adapter = adapter | ||
| adjustToolbar(binding.root, adapter) | ||
| decksAdapter = DecksArrayAdapter(decks) | ||
| binding.list.adapter = decksAdapter | ||
| adjustToolbar(binding.root, decksAdapter) | ||
| dialog = | ||
| AlertDialog.Builder(requireActivity()).create { | ||
| negativeButton(R.string.dialog_cancel) | ||
|
|
@@ -239,13 +240,26 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |
|
|
||
| var deckCreationListener: DeckCreationListener? = null | ||
|
|
||
| private val keepOpen: Boolean | ||
| get() = requireArguments().getBoolean(KEEP_OPEN) | ||
|
|
||
| /** | ||
| * Same action as pressing on the deck in the list. I.e. send the deck to listener and close the dialog. | ||
| * When [keepOpen] is true, the dialog stays open and removes the selected deck from the list. | ||
| */ | ||
| protected fun selectDeckAndClose(deck: SelectableDeck) { | ||
| Timber.d("selected deck '%s'", deck) | ||
| onDeckSelected(deck) | ||
| dialog!!.dismiss() | ||
| if (keepOpen) { | ||
| if (deck is SelectableDeck.Deck) { | ||
| decksAdapter.removeDeck(deck.deckId) | ||
| } | ||
| if (decksAdapter.itemCount == 0) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a quick comment would be useful |
||
| dialog?.dismiss() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might as well use |
||
| } | ||
| } else { | ||
| dialog!!.dismiss() | ||
| } | ||
| } | ||
|
|
||
| protected fun displayErrorAndCancel() { | ||
|
|
@@ -308,6 +322,11 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |
| notifyDataSetChanged() | ||
| } | ||
|
|
||
| fun removeDeck(deckId: DeckId) { | ||
| allDecksList.removeAll { it.did == deckId } | ||
| updateCurrentlyDisplayedDecks() | ||
| } | ||
|
|
||
| private val allDecksList = ArrayList<DeckNode>() | ||
| private val currentlyDisplayedDecks = ArrayList<DeckNode>() | ||
|
|
||
|
|
@@ -437,6 +456,7 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |
| private const val TITLE = "title" | ||
| private const val KEEP_RESTORE_DEFAULT_BUTTON = "keepRestoreDefaultButton" | ||
| private const val DECK_NAMES = "deckNames" | ||
| private const val KEEP_OPEN = "keepOpen" | ||
|
|
||
| /** | ||
| * A dialog which handles selecting a deck | ||
|
|
@@ -446,13 +466,15 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |
| summaryMessage: String?, | ||
| keepRestoreDefaultButton: Boolean, | ||
| decks: List<SelectableDeck>, | ||
| keepOpen: Boolean = false, | ||
| ): DeckSelectionDialog { | ||
| val f = DeckSelectionDialog() | ||
| val args = Bundle() | ||
| args.putString(SUMMARY_MESSAGE, summaryMessage) | ||
| args.putString(TITLE, title) | ||
| args.putBoolean(KEEP_RESTORE_DEFAULT_BUTTON, keepRestoreDefaultButton) | ||
| args.putParcelableArrayList(DECK_NAMES, ArrayList(decks)) | ||
| args.putBoolean(KEEP_OPEN, keepOpen) | ||
| f.arguments = args | ||
| return f | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -154,8 +154,6 @@ class DeckPickerWidgetConfig : | |
|
|
||
| setupDoneButton() | ||
|
|
||
| // TODO: Implement multi-select functionality so that user can select desired decks in once. | ||
| // TODO: Implement a functionality to hide already selected deck. | ||
| binding.fabWidgetDeckPicker.setOnClickListener { | ||
| showDeckSelectionDialog() | ||
| } | ||
|
|
@@ -302,10 +300,10 @@ class DeckPickerWidgetConfig : | |
| } | ||
| } | ||
|
|
||
| /** Asynchronously displays the list of deck in the selection dialog. */ | ||
| /** Displays the deck selection dialog, filtering out already-selected decks. */ | ||
| private fun showDeckSelectionDialog() { | ||
| lifecycleScope.launch { | ||
| val decks = fetchDecks() | ||
| val decks = fetchDecks().filter { it.deckId !in deckAdapter.deckIds } | ||
| displayDeckSelectionDialog(decks) | ||
| } | ||
| } | ||
|
|
@@ -324,8 +322,13 @@ class DeckPickerWidgetConfig : | |
| summaryMessage = null, | ||
| keepRestoreDefaultButton = false, | ||
| decks = decks, | ||
| keepOpen = true, | ||
| ) | ||
| dialog.show(supportFragmentManager, "DeckSelectionDialog") | ||
| dialog.show(supportFragmentManager, DECK_SELECTION_DIALOG_TAG) | ||
| } | ||
|
|
||
| private fun dismissDeckSelectionDialog() { | ||
| (supportFragmentManager.findFragmentByTag(DECK_SELECTION_DIALOG_TAG) as? DeckSelectionDialog)?.dismiss() | ||
| } | ||
|
|
||
| /** Called when a deck is selected from the deck selection dialog. */ | ||
|
|
@@ -338,31 +341,27 @@ class DeckPickerWidgetConfig : | |
| val isDeckAlreadySelected = deckAdapter.deckIds.contains(deck.deckId) | ||
|
|
||
| if (isDeckAlreadySelected) { | ||
| // TODO: Eventually, ensure that the user can't select a deck that is already selected. | ||
| showSnackbar(getString(R.string.deck_already_selected_message)) | ||
| return | ||
| } | ||
|
|
||
| // Check if the deck is being added to a fully occupied selection | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lots of comments are removed, why? |
||
| if (deckAdapter.itemCount >= MAX_DECKS_ALLOWED) { | ||
| // Snackbar will only be shown when adding the 5th deck | ||
| if (deckAdapter.itemCount == MAX_DECKS_ALLOWED) { | ||
| showSnackbar(resources.getQuantityString(R.plurals.deck_limit_reached, MAX_DECKS_ALLOWED, MAX_DECKS_ALLOWED)) | ||
| } | ||
| // The FAB visibility should be handled in updateFabVisibility() | ||
| } else { | ||
| // Add the deck and update views | ||
| deckAdapter.addDeck(deck) | ||
| updateViewVisibility() | ||
| updateFabVisibility() | ||
| setupDoneButton() | ||
| hasUnsavedChanges = true | ||
| setUnsavedChanges(true) | ||
| return | ||
| } | ||
|
|
||
| // Show snackbar if the deck is the 5th deck | ||
| if (deckAdapter.itemCount == MAX_DECKS_ALLOWED) { | ||
| showSnackbar(resources.getQuantityString(R.plurals.deck_limit_reached, MAX_DECKS_ALLOWED, MAX_DECKS_ALLOWED)) | ||
| } | ||
| deckAdapter.addDeck(deck) | ||
| updateViewVisibility() | ||
| updateFabVisibility() | ||
| setupDoneButton() | ||
| hasUnsavedChanges = true | ||
| setUnsavedChanges(true) | ||
|
|
||
| if (deckAdapter.itemCount == MAX_DECKS_ALLOWED) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. explain with a comment |
||
| showSnackbar(resources.getQuantityString(R.plurals.deck_limit_reached, MAX_DECKS_ALLOWED, MAX_DECKS_ALLOWED)) | ||
| dismissDeckSelectionDialog() | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -459,9 +458,7 @@ class DeckPickerWidgetConfig : | |
| } | ||
|
|
||
| companion object { | ||
| /** | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this removed? |
||
| * Maximum number of decks allowed in the widget. | ||
| */ | ||
| private const val MAX_DECKS_ALLOWED = 5 | ||
| private const val DECK_SELECTION_DIALOG_TAG = "DeckSelectionDialog" | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multi-select is more clear than 'keep open'