-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Integrate image occlusion editor #14884
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
Changes from 1 commit
0a794d6
8b58483
474b077
8e084e4
d10c1e3
834ec12
1fcaf64
d8027cd
8facba1
ba94433
47b1247
c09efa4
2014063
385f59e
6ba377f
d92941d
c2fd7f0
e3615ff
d1de5e9
84ba4b7
3e2047e
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 |
|---|---|---|
|
|
@@ -49,6 +49,7 @@ import androidx.core.content.edit | |
| import androidx.core.content.res.ResourcesCompat | ||
| import androidx.core.text.HtmlCompat | ||
| import anki.config.ConfigKey | ||
| import anki.notetypes.StockNotetype | ||
| import com.google.android.material.color.MaterialColors | ||
| import com.google.android.material.snackbar.Snackbar | ||
| import com.ichi2.anim.ActivityTransitionAnimation | ||
|
|
@@ -74,6 +75,7 @@ import com.ichi2.anki.noteeditor.FieldState.FieldChangeType | |
| import com.ichi2.anki.noteeditor.Toolbar | ||
| import com.ichi2.anki.noteeditor.Toolbar.TextFormatListener | ||
| import com.ichi2.anki.noteeditor.Toolbar.TextWrapper | ||
| import com.ichi2.anki.pages.ImageOcclusion | ||
| import com.ichi2.anki.preferences.sharedPrefs | ||
| import com.ichi2.anki.receiver.SdCardReceiver | ||
| import com.ichi2.anki.servicelayer.LanguageHintService | ||
|
|
@@ -95,6 +97,7 @@ import com.ichi2.libanki.exception.ConfirmModSchemaException | |
| import com.ichi2.utils.* | ||
| import com.ichi2.widget.WidgetStatus | ||
| import org.json.JSONArray | ||
| import org.json.JSONException | ||
| import org.json.JSONObject | ||
| import timber.log.Timber | ||
| import java.util.* | ||
|
|
@@ -240,6 +243,17 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags | |
| } | ||
| ) | ||
|
|
||
| private val requestIOEditorLauncher = registerForActivityResult( | ||
| ActivityResultContracts.StartActivityForResult(), | ||
| NoteEditorActivityResultCallback { result -> | ||
| if (result.resultCode != RESULT_CANCELED) { | ||
| ImportUtils.getFileCachedCopy(this@NoteEditor, result.data!!)?.let { path -> | ||
| setupImageOcclusionEditor(path) | ||
| } | ||
| } | ||
| } | ||
| ) | ||
|
|
||
| private inner class NoteEditorActivityResultCallback(private val callback: (result: ActivityResult) -> Unit) : ActivityResultCallback<ActivityResult> { | ||
| override fun onActivityResult(result: ActivityResult) { | ||
| Timber.d("onActivityResult() with result: %s", result.resultCode) | ||
|
|
@@ -447,6 +461,25 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags | |
| else -> {} | ||
| } | ||
|
|
||
| col.backend.addImageOcclusionNotetype() | ||
|
||
|
|
||
| val imageOcclusionButton: Button = findViewById(R.id.ImageOcclusionButton) | ||
| if (addNote) { | ||
| imageOcclusionButton.setText(R.string.select_image) | ||
| imageOcclusionButton.setOnClickListener { | ||
| val i = Intent() | ||
| i.type = "image/*" | ||
| i.action = Intent.ACTION_GET_CONTENT | ||
| i.addCategory(Intent.CATEGORY_OPENABLE) | ||
| launchActivityForResultWithAnimation(Intent.createChooser(i, resources.getString(R.string.select_image)), requestIOEditorLauncher, START) | ||
| } | ||
| } else { | ||
| imageOcclusionButton.setText(R.string.edit_occlusions) | ||
| imageOcclusionButton.setOnClickListener { | ||
| setupImageOcclusionEditor() | ||
| } | ||
| } | ||
|
|
||
| // Note type Selector | ||
| mNoteTypeSpinner = findViewById(R.id.note_type_spinner) | ||
| mAllModelIds = setupNoteTypeSpinner(this, mNoteTypeSpinner!!, col) | ||
|
|
@@ -1252,6 +1285,15 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags | |
| val editLines = mFieldState.loadFieldEditLines(type) | ||
| mFieldsLayoutContainer!!.removeAllViews() | ||
| mCustomViewIds.clear() | ||
| if (currentNotetypeIsImageOcclusion()) { | ||
| setImageOcclusionButton() | ||
| return | ||
| } else { | ||
| val imageOcclusionButton: Button = findViewById(R.id.ImageOcclusionButton) | ||
| imageOcclusionButton.visibility = View.GONE | ||
| mFieldsLayoutContainer?.visibility = View.VISIBLE | ||
| } | ||
|
|
||
| mEditFields = LinkedList() | ||
|
|
||
| var previous: FieldEditLine? = null | ||
|
|
@@ -1926,6 +1968,35 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags | |
| val fieldsFromSelectedNote: Array<Array<String>> | ||
| get() = mEditorNote!!.items().map { it.requireNoNulls() }.toTypedArray() | ||
|
|
||
| private fun currentNotetypeIsImageOcclusion(): Boolean { | ||
| println("currentNotetypeIsImageOcclusion: ${currentlySelectedNotetype?.fieldsNames}") | ||
|
||
| try { | ||
| return currentlySelectedNotetype?.getInt("originalStockKind") == StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_IMAGE_OCCLUSION_VALUE | ||
| } catch (j: JSONException) { | ||
| return false | ||
| } | ||
| } | ||
|
|
||
| private fun setImageOcclusionButton() { | ||
| val imageOcclusionButton: Button = findViewById(R.id.ImageOcclusionButton) | ||
| imageOcclusionButton.visibility = View.VISIBLE | ||
| mFieldsLayoutContainer?.visibility = View.GONE | ||
| } | ||
|
|
||
| private fun setupImageOcclusionEditor(imagePath: String = "") { | ||
| val kind: String | ||
| val id: Long | ||
| if (addNote) { | ||
| kind = "add" | ||
| id = 0 | ||
| } else { | ||
| kind = "edit" | ||
| id = mEditorNote?.id!! | ||
| } | ||
| val intent = ImageOcclusion.getIntent(this@NoteEditor, kind, id, imagePath) | ||
| startActivity(intent) | ||
| } | ||
|
|
||
| // ---------------------------------------------------------------------------- | ||
| // INNER CLASSES | ||
| // ---------------------------------------------------------------------------- | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,6 +93,11 @@ open class AnkiServer( | |
| "setWantsAbort" -> CollectionManager.getBackend().setWantsAbortRaw(bytes) | ||
| "evaluateWeights" -> withCol { evaluateWeightsRaw(bytes) } | ||
| "latestProgress" -> CollectionManager.getBackend().latestProgressRaw(bytes) | ||
| "getImageForOcclusion" -> CollectionManager.getBackend().getImageForOcclusionRaw(bytes) | ||
| "getImageOcclusionNote" -> CollectionManager.getBackend().getImageOcclusionNoteRaw(bytes) | ||
| "getImageForOcclusionFields" -> CollectionManager.getBackend().getImageOcclusionFieldsRaw(bytes) | ||
| "addImageOcclusionNote" -> CollectionManager.getBackend().addImageOcclusionNoteRaw(bytes) | ||
| "updateImageOcclusionNote" -> CollectionManager.getBackend().updateImageOcclusionNoteRaw(bytes) | ||
|
||
| else -> { throw Exception("unhandled request: $methodName") } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| /* | ||
| * Copyright (c) 2023 Abdo <abdo@abdnh.net> | ||
| * | ||
| * 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.pages | ||
|
|
||
| import android.content.Context | ||
| import android.content.Intent | ||
| import android.os.Bundle | ||
| import android.webkit.WebView | ||
| import com.ichi2.anki.R | ||
| import org.json.JSONObject | ||
|
|
||
| class ImageOcclusion : PageFragment() { | ||
|
|
||
| override val title = R.string.image_occlusion | ||
|
||
| override val pageName = "image-occlusion" | ||
| override lateinit var webViewClient: PageWebViewClient | ||
| override var webChromeClient = PageChromeClient() | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| val kind = arguments?.getString(ARG_KEY_KIND) ?: throw Exception("missing kind") | ||
| val id = arguments?.getLong(ARG_KEY_ID) ?: throw Exception("missing ID") | ||
| val path = arguments?.getString(ARG_KEY_PATH) ?: if (kind == "add") throw Exception("missing path") else "" | ||
| webViewClient = ImageOcclusionWebViewClient(kind, id, path) | ||
| super.onCreate(savedInstanceState) | ||
| } | ||
|
|
||
| class ImageOcclusionWebViewClient(val kind: String, private val noteOrNotetypeId: Long, private val path: String?) : PageWebViewClient() { | ||
| override fun onPageFinished(view: WebView?, url: String?) { | ||
| val options = JSONObject() | ||
| options.put("kind", kind) | ||
| options.put("imagePath", path) | ||
| if (kind == "add") { | ||
| options.put("notetypeId", noteOrNotetypeId) | ||
| } else { | ||
| options.put("noteId", noteOrNotetypeId) | ||
| } | ||
| view!!.evaluateJavascript("anki.setupImageOcclusion($options);") { | ||
| super.onPageFinished(view, url) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| companion object { | ||
| private const val ARG_KEY_KIND = "kind" | ||
| private const val ARG_KEY_ID = "id" | ||
| private const val ARG_KEY_PATH = "path" | ||
|
|
||
| fun getIntent(context: Context, kind: String, noteOrNotetypeId: Long, imagePath: String?): Intent { | ||
| val arguments = Bundle().apply { | ||
|
||
| putString(ARG_KEY_KIND, kind) | ||
| putLong(ARG_KEY_ID, noteOrNotetypeId) | ||
| putString(ARG_KEY_PATH, imagePath) | ||
| } | ||
| return PagesActivity.getIntent(context, ImageOcclusion::class, arguments) | ||
| } | ||
| } | ||
| } | ||
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.
I believe this can use
https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts.GetContent