@@ -21,21 +21,36 @@ import android.net.Uri
2121import android.os.Bundle
2222import android.view.View
2323import android.webkit.WebView
24+ import android.widget.Spinner
2425import androidx.activity.addCallback
2526import androidx.core.os.bundleOf
27+ import androidx.fragment.app.viewModels
2628import androidx.lifecycle.lifecycleScope
2729import com.google.android.material.appbar.MaterialToolbar
2830import com.ichi2.anki.CollectionManager.withCol
31+ import com.ichi2.anki.DeckSpinnerSelection
2932import com.ichi2.anki.R
3033import com.ichi2.anki.SingleFragmentActivity
3134import com.ichi2.anki.common.annotations.NeedsTest
35+ import com.ichi2.anki.dialogs.DeckSelectionDialog
3236import com.ichi2.anki.dialogs.DiscardChangesDialog
37+ import com.ichi2.anki.launchCatchingTask
3338import com.ichi2.anki.libanki.DeckId
39+ import com.ichi2.anki.libanki.DeckNameId
40+ import com.ichi2.anki.model.SelectableDeck
41+ import com.ichi2.anki.pages.viewmodel.ImageOcclusionArgs
42+ import com.ichi2.anki.pages.viewmodel.ImageOcclusionViewModel
43+ import com.ichi2.anki.requireAnkiActivity
3444import kotlinx.coroutines.launch
35- import org.json.JSONObject
3645import timber.log.Timber
3746
38- class ImageOcclusion : PageFragment (R .layout.image_occlusion) {
47+ class ImageOcclusion :
48+ PageFragment (R .layout.image_occlusion),
49+ DeckSelectionDialog .DeckSelectionListener {
50+ private val viewModel: ImageOcclusionViewModel by viewModels()
51+ private lateinit var deckSpinnerSelection: DeckSpinnerSelection
52+ private lateinit var spinner: Spinner
53+
3954 override fun onViewCreated (
4055 view : View ,
4156 savedInstanceState : Bundle ? ,
@@ -49,33 +64,34 @@ class ImageOcclusion : PageFragment(R.layout.image_occlusion) {
4964 }
5065 }
5166
67+ spinner = view.findViewById(R .id.deck_selector)
68+ deckSpinnerSelection =
69+ DeckSpinnerSelection (
70+ requireAnkiActivity(),
71+ spinner,
72+ showAllDecks = false ,
73+ alwaysShowDefault = false ,
74+ showFilteredDecks = false ,
75+ )
76+
77+ requireAnkiActivity().launchCatchingTask {
78+ deckSpinnerSelection.initializeStatsBarDeckSpinner()
79+ val selectedDeck = withCol { decks.getLegacy(decks.selected()) }
80+ if (selectedDeck == null ) return @launchCatchingTask
81+ select(selectedDeck.id)
82+ }
83+
5284 @NeedsTest(" #17393 verify that the added image occlusion cards are put in the correct deck" )
5385 view.findViewById<MaterialToolbar >(R .id.toolbar).setOnMenuItemClickListener {
54- val editorWorkingDeckId = requireArguments().getLong(ARG_KEY_EDITOR_DECK_ID )
5586 if (it.itemId == R .id.action_save) {
5687 Timber .i(" save item selected" )
57- // TODO desktop code doesn't allow a deck change from the reviewer, if we would do
58- // the same then NoteEditor could simply set the deck as selected and this hack
59- // could be removed
60- // because NoteEditor doesn't update the selected deck in Collection.decks when
61- // there's a deck change and keeps its own deckId reference, we need to use that
62- // deck id reference as the target deck in this fragment(backend code simply uses
63- // the current selected deck it sees as the target deck for adding)
64- lifecycleScope.launch {
65- val previousDeckId =
66- withCol {
67- val current = backend.getCurrentDeck().id
68- backend.setCurrentDeck(editorWorkingDeckId)
69- current
70- }
71- webView.evaluateJavascript(" anki.imageOcclusion.save()" ) {
72- // reset to the previous deck that the backend "saw" as selected, this
73- // avoids other screens unexpectedly having their working decks modified(
74- // most important being the Reviewer where the user would find itself
75- // studying another deck after editing a note with changing the deck)
76- lifecycleScope.launch {
77- withCol { backend.setCurrentDeck(previousDeckId) }
78- }
88+ webView.evaluateJavascript(" anki.imageOcclusion.save()" ) {
89+ // reset to the previous deck that the backend "saw" as selected, this
90+ // avoids other screens unexpectedly having their working decks modified(
91+ // most important being the Reviewer where the user would find itself
92+ // studying another deck after editing a note with changing the deck)
93+ viewLifecycleOwner.lifecycleScope.launch {
94+ viewModel.onSaveOperationCompleted()
7995 }
8096 }
8197 }
@@ -90,32 +106,44 @@ class ImageOcclusion : PageFragment(R.layout.image_occlusion) {
90106 url : String? ,
91107 ) {
92108 super .onPageFinished(view, url)
109+ viewModel.webViewOptions.let { options ->
110+ view?.evaluateJavascript(" globalThis.anki.imageOcclusion.mode = $options " ) {
111+ super .onPageFinished(view, url)
112+ }
113+ }
114+ }
115+ }
93116
94- val kind = requireArguments().getString( ARG_KEY_KIND )
95- val noteOrNotetypeId = requireArguments().getLong( ARG_KEY_ID )
96- val imagePath = requireArguments().getString( ARG_KEY_PATH )
117+ override fun onDeckSelected ( deck : SelectableDeck ? ) {
118+ if (deck == null ) return
119+ require(deck is SelectableDeck . Deck )
97120
98- val options = JSONObject ( )
99- options.put( " kind " , kind)
100- if (kind == " add " ) {
101- options.put( " imagePath " , imagePath )
102- options.put( " notetypeId " , noteOrNotetypeId )
103- } else {
104- options.put( " noteId " , noteOrNotetypeId)
105- }
121+ val deckDidChange = viewModel.handleDeckSelection(deck.deckId )
122+ if (deckDidChange) {
123+ viewLifecycleOwner.lifecycleScope.launch {
124+ select(deck.deckId )
125+ deckSpinnerSelection.selectDeckById(viewModel.selectedDeckId, true )
126+ }
127+ }
128+ }
106129
107- view?.evaluateJavascript(" globalThis.anki.imageOcclusion.mode = $options " ) {
108- super .onPageFinished(view, url)
130+ private val decksAdapterSequence
131+ get() =
132+ sequence {
133+ for (i in 0 until spinner.adapter.count) {
134+ yield (spinner.adapter.getItem(i) as DeckNameId )
109135 }
110136 }
111- }
112137
113- companion object {
114- private const val ARG_KEY_KIND = " kind"
115- private const val ARG_KEY_ID = " id"
116- private const val ARG_KEY_PATH = " imagePath"
117- private const val ARG_KEY_EDITOR_DECK_ID = " arg_key_editor_deck_id"
138+ /* *
139+ * Given the [deckId] look in the decks adapter for its position and select it if found.
140+ */
141+ private fun select (deckId : DeckId ) {
142+ val itemToSelect = decksAdapterSequence.withIndex().firstOrNull { it.value.id == deckId } ? : return
143+ spinner.setSelection(itemToSelect.index)
144+ }
118145
146+ companion object {
119147 /* *
120148 * @param editorWorkingDeckId the current deck id that [com.ichi2.anki.NoteEditorFragment] is using
121149 */
@@ -134,11 +162,11 @@ class ImageOcclusion : PageFragment(R.layout.image_occlusion) {
134162 }
135163 val arguments =
136164 bundleOf(
137- ARG_KEY_KIND to kind,
138- ARG_KEY_ID to noteOrNotetypeId,
139- ARG_KEY_PATH to imagePath,
165+ ImageOcclusionArgs . KEY_KIND to kind,
166+ ImageOcclusionArgs . KEY_ID to noteOrNotetypeId,
167+ ImageOcclusionArgs . KEY_PATH to imagePath,
140168 PATH_ARG_KEY to " image-occlusion/$suffix " ,
141- ARG_KEY_EDITOR_DECK_ID to editorWorkingDeckId,
169+ ImageOcclusionArgs . KEY_EDITOR_DECK_ID to editorWorkingDeckId,
142170 )
143171 return SingleFragmentActivity .getIntent(context, ImageOcclusion ::class , arguments)
144172 }
0 commit comments