mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-19 19:42:17 +02:00
NoteEditor intent creation using NoteEditorLauncher interface
Refactored NoteEditor integration with NoteEditorLauncher interface to centralize configuration for various entry points. Introduced NoteEditorLauncher as a sealed interface to streamline and unify configurations for opening NoteEditor from different contexts. Provides clear and standardized methods (e.g., AddNote, EditCard) for invoking NoteEditor with specific behaviors and data, improving code clarity and reducing potential errors in bundle creation. Promotes modularization by consolidating NoteEditor-related logic into a single location (noteeditor folder), enhancing maintainability and reducing redundancy across fragments and activities. - ImageOcclusion: Handles opening NoteEditor with an image URI for creating an image occlusion. - PassArguments: Directly passes arguments to the NoteEditor for scenarios like sharing text or processing text. - AddNote: Opens NoteEditor from DeckPicker with optional deck ID. - AddNoteFromCardBrowser: Opens NoteEditor from CardBrowser, optionally passing search terms and last deck ID. - AddNoteFromReviewer: Opens NoteEditor from Reviewer, optionally specifying activity transition animation. - AddInstantNote: Opens NoteEditor for instant note creation with shared text. - EditCard: Edits a card in NoteEditor, specifying card ID and animation direction. - EditNoteFromPreviewer: Edits a note in NoteEditor from Previewer, using the card ID. - CopyNote: Copies a note in NoteEditor, optionally specifying deck ID, field texts, and tags.
This commit is contained in:
parent
ba341fc788
commit
336736faec
@ -16,11 +16,12 @@
|
||||
package com.ichi2.anki
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.ichi2.anki.NoteEditor.Companion.intentLaunchedWithImage
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.tests.InstrumentedTest
|
||||
import com.ichi2.anki.testutil.GrantStoragePermission
|
||||
import com.ichi2.anki.testutil.getEditor
|
||||
@ -71,11 +72,7 @@ class NoteEditorIntentTest : InstrumentedTest() {
|
||||
|
||||
private val noteEditorTextIntent: Intent
|
||||
get() {
|
||||
val bundle = Bundle().apply {
|
||||
putString(Intent.EXTRA_TEXT, "sample text")
|
||||
}
|
||||
val intent = NoteEditor.getIntent(testContext, bundle)
|
||||
intent.action = Intent.ACTION_SEND
|
||||
return intent
|
||||
val bundle = bundleOf(Intent.EXTRA_TEXT to "sample text")
|
||||
return NoteEditorLauncher.PassArguments(bundle).getIntent(testContext, Intent.ACTION_SEND)
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ package com.ichi2.anki
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.testutil.GrantStoragePermission
|
||||
import com.ichi2.utils.KotlinCleanup
|
||||
import org.hamcrest.Matchers.equalTo
|
||||
@ -41,10 +41,7 @@ abstract class NoteEditorTest protected constructor() {
|
||||
|
||||
private val noteEditorIntent: Intent
|
||||
get() {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_DECKPICKER)
|
||||
}
|
||||
return NoteEditor.getIntent(targetContext, bundle)
|
||||
return NoteEditorLauncher.AddNote().getIntent(targetContext)
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -105,8 +105,7 @@ import com.ichi2.anki.dialogs.tags.TagsDialog
|
||||
import com.ichi2.anki.dialogs.tags.TagsDialogFactory
|
||||
import com.ichi2.anki.dialogs.tags.TagsDialogListener
|
||||
import com.ichi2.anki.model.CardStateFilter
|
||||
import com.ichi2.anki.noteeditor.EditCardDestination
|
||||
import com.ichi2.anki.noteeditor.toIntent
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.pages.AnkiServer
|
||||
import com.ichi2.anki.pages.CongratsPage
|
||||
import com.ichi2.anki.pages.PostRequestHandler
|
||||
@ -847,7 +846,7 @@ abstract class AbstractFlashcardViewer :
|
||||
return
|
||||
}
|
||||
val animation = fromGesture.toAnimationTransition().invert()
|
||||
val editCardIntent = EditCardDestination(currentCard!!.id).toIntent(this, animation)
|
||||
val editCardIntent = NoteEditorLauncher.EditCard(currentCard!!.id, animation).getIntent(this)
|
||||
editCurrentCardLauncher.launch(editCardIntent)
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,7 @@ import com.ichi2.anki.model.CardsOrNotes
|
||||
import com.ichi2.anki.model.CardsOrNotes.CARDS
|
||||
import com.ichi2.anki.model.CardsOrNotes.NOTES
|
||||
import com.ichi2.anki.model.SortType
|
||||
import com.ichi2.anki.noteeditor.EditCardDestination
|
||||
import com.ichi2.anki.noteeditor.toIntent
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.preferences.sharedPrefs
|
||||
import com.ichi2.anki.previewer.PreviewerFragment
|
||||
import com.ichi2.anki.receiver.SdCardReceiver
|
||||
@ -713,7 +712,7 @@ open class CardBrowser :
|
||||
@NeedsTest("I/O edits are saved")
|
||||
private fun openNoteEditorForCard(cardId: CardId) {
|
||||
currentCardId = cardId
|
||||
val intent = EditCardDestination(currentCardId).toIntent(this, animation = Direction.DEFAULT)
|
||||
val intent = NoteEditorLauncher.EditCard(currentCardId, Direction.DEFAULT).getIntent(this)
|
||||
onEditCardActivityResult.launch(intent)
|
||||
// #6432 - FIXME - onCreateOptionsMenu crashes if receiving an activity result from edit card when in multiselect
|
||||
viewModel.endMultiSelectMode()
|
||||
@ -2222,14 +2221,7 @@ open class CardBrowser :
|
||||
|
||||
@VisibleForTesting
|
||||
fun createAddNoteIntent(context: Context, viewModel: CardBrowserViewModel): Intent {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_CARDBROWSER_ADD)
|
||||
if (viewModel.lastDeckId?.let { id -> id > 0 } == true) {
|
||||
putLong(NoteEditor.EXTRA_DID, viewModel.lastDeckId!!)
|
||||
}
|
||||
putString(NoteEditor.EXTRA_TEXT_FROM_SEARCH_VIEW, viewModel.searchTerms)
|
||||
}
|
||||
return NoteEditor.getIntent(context, bundle)
|
||||
return NoteEditorLauncher.AddNoteFromCardBrowser(viewModel).getIntent(context)
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
|
@ -135,6 +135,7 @@ import com.ichi2.anki.export.ExportDialogsFactory
|
||||
import com.ichi2.anki.export.ExportDialogsFactoryProvider
|
||||
import com.ichi2.anki.introduction.CollectionPermissionScreenLauncher
|
||||
import com.ichi2.anki.introduction.hasCollectionStoragePermissions
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.notetype.ManageNotetypes
|
||||
import com.ichi2.anki.pages.AnkiPackageImporterFragment
|
||||
import com.ichi2.anki.pages.CongratsPage
|
||||
@ -1511,10 +1512,7 @@ open class DeckPicker :
|
||||
}
|
||||
|
||||
fun addNote() {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_DECKPICKER)
|
||||
}
|
||||
val intent = NoteEditor.getIntent(this, bundle)
|
||||
val intent = NoteEditorLauncher.AddNote().getIntent(this)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
|
@ -19,17 +19,13 @@ package com.ichi2.anki
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
/**
|
||||
* Builder class for creating intents related to image occlusion in the [NoteEditor].
|
||||
*/
|
||||
class ImageOcclusionIntentBuilder(private val context: Context) {
|
||||
|
||||
fun buildIntent(imageUri: Uri?): Intent {
|
||||
val bundle = Bundle().apply {
|
||||
putParcelable(NoteEditor.EXTRA_IMG_OCCLUSION, imageUri)
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_IMG_OCCLUSION)
|
||||
}
|
||||
return NoteEditor.getIntent(context, bundle)
|
||||
return NoteEditorLauncher.ImageOcclusion(imageUri).getIntent(context)
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.ichi2.anki
|
||||
|
||||
import android.os.Bundle
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
@ -33,7 +34,7 @@ class IntentHandler2 : AbstractIntentHandler() {
|
||||
Timber.i("Intent contained an image")
|
||||
intent.putExtra(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_ADD_IMAGE)
|
||||
}
|
||||
val noteEditorIntent = NoteEditor.getIntent(this, intent.extras!!, intent.action)
|
||||
val noteEditorIntent = NoteEditorLauncher.PassArguments(intent.extras!!).getIntent(this, intent.action)
|
||||
noteEditorIntent.setDataAndType(intent.data, intent.type)
|
||||
startActivity(noteEditorIntent)
|
||||
finish()
|
||||
|
@ -100,6 +100,7 @@ import com.ichi2.anki.multimediacard.impl.MultimediaEditableNote
|
||||
import com.ichi2.anki.noteeditor.CustomToolbarButton
|
||||
import com.ichi2.anki.noteeditor.FieldState
|
||||
import com.ichi2.anki.noteeditor.FieldState.FieldChangeType
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.noteeditor.Toolbar.TextFormatListener
|
||||
import com.ichi2.anki.noteeditor.Toolbar.TextWrapper
|
||||
import com.ichi2.anki.pages.ImageOcclusion
|
||||
@ -1355,25 +1356,17 @@ class NoteEditor : AnkiFragment(R.layout.note_editor), DeckSelectionListener, Su
|
||||
}
|
||||
|
||||
private fun addNewNote() {
|
||||
openNewNoteEditor { }
|
||||
launchNoteEditor(NoteEditorLauncher.AddNote(deckId)) { }
|
||||
}
|
||||
|
||||
fun copyNote() {
|
||||
openNewNoteEditor { bundle: Bundle ->
|
||||
bundle.putString(EXTRA_CONTENTS, fieldsText)
|
||||
if (selectedTags != null) {
|
||||
bundle.putStringArray(EXTRA_TAGS, selectedTags!!.toTypedArray())
|
||||
}
|
||||
}
|
||||
launchNoteEditor(NoteEditorLauncher.CopyNote(deckId, fieldsText, selectedTags)) { }
|
||||
}
|
||||
|
||||
private fun openNewNoteEditor(intentEnricher: Consumer<Bundle>) {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(EXTRA_CALLER, CALLER_NOTEEDITOR)
|
||||
putLong(EXTRA_DID, deckId)
|
||||
}
|
||||
val intent = getIntent(requireContext(), bundle)
|
||||
// mutate event with additional properties
|
||||
private fun launchNoteEditor(arguments: NoteEditorLauncher, intentEnricher: Consumer<Bundle>) {
|
||||
val intent = arguments.getIntent(requireContext())
|
||||
val bundle = arguments.toBundle()
|
||||
// Mutate event with additional properties
|
||||
intentEnricher.accept(bundle)
|
||||
requestAddLauncher.launch(intent)
|
||||
}
|
||||
@ -2565,9 +2558,5 @@ class NoteEditor : AnkiFragment(R.layout.note_editor), DeckSelectionListener, Su
|
||||
return !AnkiDroidApp.instance.sharedPrefs()
|
||||
.getBoolean(PREF_NOTE_EDITOR_SHOW_TOOLBAR, true)
|
||||
}
|
||||
|
||||
fun getIntent(context: Context, arguments: Bundle, action: String? = null): Intent {
|
||||
return SingleFragmentActivity.getIntent(context, NoteEditor::class, arguments, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ import com.ichi2.anki.Whiteboard.Companion.createInstance
|
||||
import com.ichi2.anki.Whiteboard.OnPaintColorChangeListener
|
||||
import com.ichi2.anki.cardviewer.Gesture
|
||||
import com.ichi2.anki.cardviewer.ViewerCommand
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.pages.AnkiServer.Companion.ANKIDROID_JS_PREFIX
|
||||
import com.ichi2.anki.pages.AnkiServer.Companion.ANKI_PREFIX
|
||||
import com.ichi2.anki.pages.CardInfoDestination
|
||||
@ -686,11 +687,8 @@ open class Reviewer :
|
||||
|
||||
fun addNote(fromGesture: Gesture? = null) {
|
||||
val animation = getAnimationTransitionFromGesture(fromGesture)
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_REVIEWER_ADD)
|
||||
putParcelable(FINISH_ANIMATION_EXTRA, getInverseTransition(animation) as Parcelable)
|
||||
}
|
||||
val intent = NoteEditor.getIntent(this, bundle)
|
||||
val inverseAnimation = getInverseTransition(animation)
|
||||
val intent = NoteEditorLauncher.AddNoteFromReviewer(inverseAnimation).getIntent(this)
|
||||
addNoteLauncher.launch(intent)
|
||||
}
|
||||
|
||||
|
@ -46,11 +46,11 @@ import com.ichi2.anki.AnkiActivity
|
||||
import com.ichi2.anki.CollectionManager.TR
|
||||
import com.ichi2.anki.CustomActionModeCallback
|
||||
import com.ichi2.anki.DeckSpinnerSelection
|
||||
import com.ichi2.anki.NoteEditor
|
||||
import com.ichi2.anki.R
|
||||
import com.ichi2.anki.dialogs.DeckSelectionDialog
|
||||
import com.ichi2.anki.dialogs.DiscardChangesDialog
|
||||
import com.ichi2.anki.launchCatchingTask
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.servicelayer.NoteService
|
||||
import com.ichi2.anki.showThemedToast
|
||||
import com.ichi2.anki.withProgress
|
||||
@ -183,11 +183,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect
|
||||
|
||||
private fun openNoteEditor() {
|
||||
val sharedText = clozeEditTextField.text.toString()
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.INSTANT_NOTE_EDITOR)
|
||||
putString(Intent.EXTRA_TEXT, sharedText)
|
||||
}
|
||||
val noteEditorIntent = NoteEditor.getIntent(this, bundle)
|
||||
val noteEditorIntent = NoteEditorLauncher.AddInstantNote(sharedText).getIntent(this)
|
||||
startActivity(noteEditorIntent)
|
||||
finish()
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 David Allison <davidallisongithub@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.ichi2.anki.noteeditor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.CheckResult
|
||||
import com.ichi2.anim.ActivityTransitionAnimation
|
||||
import com.ichi2.anki.AnkiActivity
|
||||
import com.ichi2.anki.NoteEditor
|
||||
import com.ichi2.libanki.CardId
|
||||
|
||||
/**
|
||||
* Opens the [Note Editor][NoteEditor] to the note of a selected card
|
||||
*
|
||||
* As the card of the note is known, additional context is provided to the UI
|
||||
*/
|
||||
data class EditCardDestination(val cardId: CardId)
|
||||
|
||||
@CheckResult
|
||||
fun EditCardDestination.toIntent(context: Context, animation: ActivityTransitionAnimation.Direction): Intent {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_EDIT)
|
||||
putLong(NoteEditor.EXTRA_CARD_ID, cardId)
|
||||
putParcelable(AnkiActivity.FINISH_ANIMATION_EXTRA, animation as Parcelable)
|
||||
}
|
||||
return NoteEditor.getIntent(context, bundle)
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Sanjay Sargam <sargamsanjaykumar@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.ichi2.anki.noteeditor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import androidx.core.os.bundleOf
|
||||
import com.ichi2.anim.ActivityTransitionAnimation
|
||||
import com.ichi2.anki.AnkiActivity
|
||||
import com.ichi2.anki.NoteEditor
|
||||
import com.ichi2.anki.SingleFragmentActivity
|
||||
import com.ichi2.anki.browser.CardBrowserViewModel
|
||||
import com.ichi2.libanki.CardId
|
||||
import com.ichi2.libanki.DeckId
|
||||
|
||||
/**
|
||||
* Defines various configurations for opening the NoteEditor fragment with specific data or actions.
|
||||
*/
|
||||
sealed interface NoteEditorLauncher {
|
||||
|
||||
/**
|
||||
* Generates an intent to open the NoteEditor fragment with the configured parameters.
|
||||
*
|
||||
* @param context The context from which the intent is launched.
|
||||
* @param action Optional action string for the intent.
|
||||
* @return Intent configured to launch the NoteEditor fragment.
|
||||
*/
|
||||
fun getIntent(context: Context, action: String? = null) =
|
||||
SingleFragmentActivity.getIntent(context, NoteEditor::class, toBundle(), action)
|
||||
|
||||
/**
|
||||
* Converts the configuration into a Bundle to pass arguments to the NoteEditor fragment.
|
||||
*
|
||||
* @return Bundle containing arguments specific to this configuration.
|
||||
*/
|
||||
fun toBundle(): Bundle
|
||||
|
||||
/**
|
||||
* Represents opening the NoteEditor with an image occlusion.
|
||||
* @property imageUri The URI of the image to occlude.
|
||||
*/
|
||||
data class ImageOcclusion(val imageUri: Uri?) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_IMG_OCCLUSION,
|
||||
NoteEditor.EXTRA_IMG_OCCLUSION to imageUri
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents opening the NoteEditor with custom arguments.
|
||||
* @property arguments The bundle of arguments to pass.
|
||||
*/
|
||||
data class PassArguments(val arguments: Bundle) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle {
|
||||
return arguments
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents adding a note to the NoteEditor within a specific deck (Optional).
|
||||
* @property deckId The ID of the deck where the note should be added.
|
||||
*/
|
||||
data class AddNote(val deckId: DeckId? = null) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_DECKPICKER
|
||||
).also { bundle ->
|
||||
deckId?.let { deckId -> bundle.putLong(NoteEditor.EXTRA_DID, deckId) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents adding a note to the NoteEditor from the card browser.
|
||||
* @property viewModel The view model containing data from the card browser.
|
||||
*/
|
||||
data class AddNoteFromCardBrowser(val viewModel: CardBrowserViewModel) :
|
||||
NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle {
|
||||
val bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_CARDBROWSER_ADD,
|
||||
NoteEditor.EXTRA_TEXT_FROM_SEARCH_VIEW to viewModel.searchTerms
|
||||
)
|
||||
if (viewModel.lastDeckId?.let { id -> id > 0 } == true) {
|
||||
bundle.putLong(NoteEditor.EXTRA_DID, viewModel.lastDeckId!!)
|
||||
}
|
||||
return bundle
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents adding a note to the NoteEditor from the reviewer.
|
||||
* @property animation The animation direction to use when transitioning.
|
||||
*/
|
||||
data class AddNoteFromReviewer(val animation: ActivityTransitionAnimation.Direction? = null) :
|
||||
NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_REVIEWER_ADD
|
||||
).also { bundle ->
|
||||
animation?.let { animation ->
|
||||
bundle.putParcelable(
|
||||
AnkiActivity.FINISH_ANIMATION_EXTRA,
|
||||
animation as Parcelable
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to move from Instant note editor to standard note editor while keeping the text content
|
||||
*
|
||||
* @property sharedText The shared text content for the instant note.
|
||||
*/
|
||||
data class AddInstantNote(val sharedText: String) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.INSTANT_NOTE_EDITOR,
|
||||
Intent.EXTRA_TEXT to sharedText
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents editing a card in the NoteEditor.
|
||||
* @property cardId The ID of the card to edit.
|
||||
* @property animation The animation direction.
|
||||
*/
|
||||
data class EditCard(val cardId: CardId, val animation: ActivityTransitionAnimation.Direction) :
|
||||
NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_EDIT,
|
||||
NoteEditor.EXTRA_CARD_ID to cardId,
|
||||
AnkiActivity.FINISH_ANIMATION_EXTRA to animation as Parcelable
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents editing a note in the NoteEditor from the previewer.
|
||||
* @property cardId The ID of the card associated with the note to edit.
|
||||
*/
|
||||
data class EditNoteFromPreviewer(val cardId: Long) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_PREVIEWER_EDIT,
|
||||
NoteEditor.EXTRA_EDIT_FROM_CARD_ID to cardId
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents copying a note to the NoteEditor.
|
||||
* @property deckId The ID of the deck where the note should be copied.
|
||||
* @property fieldsText The text content of the fields to copy.
|
||||
* @property tags Optional list of tags to assign to the copied note.
|
||||
*/
|
||||
data class CopyNote(
|
||||
val deckId: DeckId,
|
||||
val fieldsText: String,
|
||||
val tags: List<String>? = null
|
||||
) : NoteEditorLauncher {
|
||||
override fun toBundle(): Bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_NOTEEDITOR,
|
||||
NoteEditor.EXTRA_DID to deckId,
|
||||
NoteEditor.EXTRA_CONTENTS to fieldsText
|
||||
).also { bundle ->
|
||||
tags?.let { tags -> bundle.putStringArray(NoteEditor.EXTRA_TAGS, tags.toTypedArray()) }
|
||||
}
|
||||
}
|
||||
}
|
@ -234,7 +234,7 @@ class PreviewerFragment :
|
||||
|
||||
private fun editCard() {
|
||||
lifecycleScope.launch {
|
||||
val intent = viewModel.getNoteEditorDestination().toIntent(requireContext())
|
||||
val intent = viewModel.getNoteEditorDestination().getIntent(requireContext())
|
||||
editCardLauncher.launch(intent)
|
||||
}
|
||||
}
|
||||
|
@ -17,24 +17,13 @@ package com.ichi2.anki.previewer
|
||||
|
||||
import android.R
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.ichi2.anki.AnkiDroidApp
|
||||
import com.ichi2.anki.LanguageUtils
|
||||
import com.ichi2.anki.NoteEditor
|
||||
import com.ichi2.themes.Themes
|
||||
import com.ichi2.utils.toRGBHex
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
class NoteEditorDestination(val cardId: Long) {
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_PREVIEWER_EDIT)
|
||||
putLong(NoteEditor.EXTRA_EDIT_FROM_CARD_ID, cardId)
|
||||
}
|
||||
fun toIntent(context: Context): Intent = NoteEditor.getIntent(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* Not exactly equal to anki's stdHtml. Some differences:
|
||||
* * `ankidroid.css` and `ankidroid.js` are added
|
||||
|
@ -28,6 +28,7 @@ import com.ichi2.anki.browser.PreviewerIdsFile
|
||||
import com.ichi2.anki.cardviewer.CardMediaPlayer
|
||||
import com.ichi2.anki.cardviewer.SingleCardSide
|
||||
import com.ichi2.anki.launchCatchingIO
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.pages.AnkiServer
|
||||
import com.ichi2.anki.reviewer.CardSide
|
||||
import com.ichi2.anki.servicelayer.MARKED_TAG
|
||||
@ -168,7 +169,7 @@ class PreviewerViewModel(previewerIdsFile: PreviewerIdsFile, firstIndex: Int, ca
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getNoteEditorDestination() = NoteEditorDestination(currentCard.await().id)
|
||||
suspend fun getNoteEditorDestination() = NoteEditorLauncher.EditNoteFromPreviewer(currentCard.await().id)
|
||||
|
||||
fun handleEditCardResult(result: ActivityResult) {
|
||||
if (result.data?.getBooleanExtra(NoteEditor.RELOAD_REQUIRED_EXTRA_KEY, false) == true ||
|
||||
|
@ -355,7 +355,7 @@ class ReviewerFragment :
|
||||
|
||||
private fun launchEditNote() {
|
||||
lifecycleScope.launch {
|
||||
val intent = viewModel.getEditNoteDestination().toIntent(requireContext())
|
||||
val intent = viewModel.getEditNoteDestination().getIntent(requireContext())
|
||||
noteEditorLauncher.launch(intent)
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,11 @@ import com.ichi2.anki.Reviewer
|
||||
import com.ichi2.anki.asyncIO
|
||||
import com.ichi2.anki.cardviewer.CardMediaPlayer
|
||||
import com.ichi2.anki.launchCatchingIO
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.pages.AnkiServer
|
||||
import com.ichi2.anki.pages.CardInfoDestination
|
||||
import com.ichi2.anki.pages.DeckOptionsDestination
|
||||
import com.ichi2.anki.previewer.CardViewerViewModel
|
||||
import com.ichi2.anki.previewer.NoteEditorDestination
|
||||
import com.ichi2.anki.reviewer.CardSide
|
||||
import com.ichi2.anki.servicelayer.MARKED_TAG
|
||||
import com.ichi2.anki.servicelayer.NoteService
|
||||
@ -181,8 +181,8 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) :
|
||||
statesMutated = true
|
||||
}
|
||||
|
||||
suspend fun getEditNoteDestination(): NoteEditorDestination {
|
||||
return NoteEditorDestination(currentCard.await().id)
|
||||
suspend fun getEditNoteDestination(): NoteEditorLauncher {
|
||||
return NoteEditorLauncher.EditNoteFromPreviewer(currentCard.await().id)
|
||||
}
|
||||
|
||||
fun refreshCard() {
|
||||
|
@ -17,13 +17,12 @@ package com.ichi2.widget
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.app.PendingIntentCompat
|
||||
import com.ichi2.anki.IntentHandler
|
||||
import com.ichi2.anki.NoteEditor
|
||||
import com.ichi2.anki.R
|
||||
import com.ichi2.anki.analytics.UsageAnalytics
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import timber.log.Timber
|
||||
|
||||
class AddNoteWidget : AppWidgetProvider() {
|
||||
@ -63,10 +62,7 @@ class AddNoteWidget : AppWidgetProvider() {
|
||||
appWidgetIds: IntArray
|
||||
) {
|
||||
val remoteViews = RemoteViews(context.packageName, R.layout.widget_add_note)
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_DECKPICKER)
|
||||
}
|
||||
val intent = NoteEditor.getIntent(context, bundle)
|
||||
val intent = NoteEditorLauncher.AddNote().getIntent(context)
|
||||
val pendingIntent = PendingIntentCompat.getActivity(context, 0, intent, 0, false)
|
||||
remoteViews.setOnClickPendingIntent(R.id.widget_add_note_button, pendingIntent)
|
||||
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews)
|
||||
|
@ -4,11 +4,11 @@ package com.ichi2.anki
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.webkit.RenderProcessGoneDetail
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.core.os.BundleCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import anki.config.ConfigKey
|
||||
@ -204,11 +204,11 @@ class AbstractFlashcardViewerTest : RobolectricTest() {
|
||||
ActivityTransitionAnimation.getInverseTransition(expectedAnimation)
|
||||
|
||||
val animation = gesture.toAnimationTransition().invert()
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_EDIT)
|
||||
putLong(NoteEditor.EXTRA_CARD_ID, viewer.currentCard!!.id)
|
||||
putParcelable(FINISH_ANIMATION_EXTRA, animation as Parcelable)
|
||||
}
|
||||
val bundle = bundleOf(
|
||||
NoteEditor.EXTRA_CALLER to NoteEditor.CALLER_EDIT,
|
||||
NoteEditor.EXTRA_CARD_ID to viewer.currentCard!!.id,
|
||||
FINISH_ANIMATION_EXTRA to animation as Parcelable
|
||||
)
|
||||
val noteEditor = NoteEditorTest().openNoteEditorWithArgs(bundle)
|
||||
val actualInverseAnimation = BundleCompat.getParcelable(
|
||||
noteEditor.requireArguments(),
|
||||
|
@ -21,7 +21,6 @@ import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.widget.EditText
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
@ -34,6 +33,7 @@ import com.ichi2.anki.NoteEditorTest.FromScreen.REVIEWER
|
||||
import com.ichi2.anki.api.AddContentApi.Companion.DEFAULT_DECK_ID
|
||||
import com.ichi2.anki.dialogs.DeckSelectionDialog.SelectableDeck
|
||||
import com.ichi2.anki.multimediacard.activity.MultimediaEditFieldActivity
|
||||
import com.ichi2.anki.noteeditor.NoteEditorLauncher
|
||||
import com.ichi2.anki.utils.ext.isImageOcclusion
|
||||
import com.ichi2.annotations.DuplicatedCode
|
||||
import com.ichi2.libanki.Consts
|
||||
@ -199,10 +199,7 @@ class NoteEditorTest : RobolectricTest() {
|
||||
@Test
|
||||
fun verifyStartupAndCloseWithNoCollectionDoesNotCrash() {
|
||||
enableNullCollection()
|
||||
val bundle = Bundle().apply {
|
||||
putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_NO_CALLER)
|
||||
}
|
||||
val intent = NoteEditor.getIntent(targetContext, bundle)
|
||||
val intent = NoteEditorLauncher.AddNote().getIntent(targetContext)
|
||||
ActivityScenario.launchActivityForResult<SingleFragmentActivity>(intent).use { scenario ->
|
||||
scenario.onNoteEditor { noteEditor ->
|
||||
noteEditor.requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
@ -519,12 +516,11 @@ class NoteEditorTest : RobolectricTest() {
|
||||
|
||||
private fun getNoteEditorAddingNote(from: FromScreen): NoteEditor {
|
||||
ensureCollectionLoadIsSynchronous()
|
||||
val bundle = Bundle().apply {
|
||||
val bundle =
|
||||
when (from) {
|
||||
REVIEWER -> putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_REVIEWER_ADD)
|
||||
DECK_LIST -> putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_DECKPICKER)
|
||||
REVIEWER -> NoteEditorLauncher.AddNoteFromReviewer().toBundle()
|
||||
DECK_LIST -> NoteEditorLauncher.AddNote().toBundle()
|
||||
}
|
||||
}
|
||||
return openNoteEditorWithArgs(bundle)
|
||||
}
|
||||
|
||||
@ -534,22 +530,16 @@ class NoteEditorTest : RobolectricTest() {
|
||||
}
|
||||
|
||||
private fun getNoteEditorEditingExistingBasicNote(n: Note, from: FromScreen): NoteEditor {
|
||||
val bundle = Bundle()
|
||||
when (from) {
|
||||
REVIEWER -> {
|
||||
bundle.putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_EDIT)
|
||||
bundle.putLong(NoteEditor.EXTRA_CARD_ID, n.firstCard().id)
|
||||
bundle.putParcelable(AnkiActivity.FINISH_ANIMATION_EXTRA, DEFAULT as Parcelable)
|
||||
val bundle =
|
||||
when (from) {
|
||||
REVIEWER -> NoteEditorLauncher.EditCard(n.firstCard().id, DEFAULT).toBundle()
|
||||
DECK_LIST -> NoteEditorLauncher.AddNote().toBundle()
|
||||
}
|
||||
DECK_LIST -> {
|
||||
bundle.putInt(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_DECKPICKER)
|
||||
}
|
||||
}
|
||||
return openNoteEditorWithArgs(bundle)
|
||||
}
|
||||
|
||||
fun openNoteEditorWithArgs(arguments: Bundle, action: String? = null): NoteEditor {
|
||||
val activity = startActivityNormallyOpenCollectionWithIntent(SingleFragmentActivity::class.java, NoteEditor.getIntent(targetContext, arguments, action))
|
||||
val activity = startActivityNormallyOpenCollectionWithIntent(SingleFragmentActivity::class.java, NoteEditorLauncher.PassArguments(arguments).getIntent(targetContext, action))
|
||||
return activity.getEditor()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user