Skip to content

Commit

Permalink
chore: update to anki 24.06.2 and adopt SvelteKit (#16449)
Browse files Browse the repository at this point in the history
* build(deps) bump anki backend to 0.1.39-anki24.06.2

* refactor: make PageFragment non abstract

some pages are now simple enough that can be created just with the path, like CardInfo

* chore: load SvelteKit assets

instead of individual pages

* chore: move CardInfo to SvelteKit

* chore: move AnkiPackageImporter to SvelteKit

* chore: move CongratsPage to SvelteKit

* chore: move CsvImporter to SvelteKit

* chore: move DeckOptions to SvelteKit

* chore: move Statistics to SvelteKit

* chore: handle POST requests in CardViewerViewModel

IO requests i18Resources now

* chore: move ImageOcclusion to SvelteKit

* refactor(PageFragment): remove unused properties
  • Loading branch information
BrayanDSO authored Jun 18, 2024
1 parent cbb64a8 commit 14813c1
Show file tree
Hide file tree
Showing 23 changed files with 185 additions and 214 deletions.
1 change: 0 additions & 1 deletion AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import android.content.Context
import android.content.Intent
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import com.ichi2.anki.pages.CardInfo.Companion.toIntent
import com.ichi2.anki.pages.CardInfoDestination
import com.ichi2.anki.pages.DeckOptions
import com.ichi2.anki.pages.PageFragment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2263,8 +2263,6 @@ abstract class AbstractFlashcardViewer :
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
pageRenderStopwatch.reset()
pageFinishedFired = false
val script = "globalThis.ankidroid = globalThis.ankidroid || {}; ankidroid.postBaseUrl = ``"
view?.evaluateJavascript(script, null)
}

override fun shouldInterceptRequest(
Expand Down
13 changes: 8 additions & 5 deletions AnkiDroid/src/main/java/com/ichi2/anki/BackendImporting.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,25 @@
package com.ichi2.anki

import android.content.Intent
import android.net.Uri
import androidx.fragment.app.FragmentActivity
import anki.collection.OpChangesOnly
import anki.import_export.ImportAnkiPackageRequest
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.libanki.buildSearchString
import com.ichi2.libanki.importAnkiPackageRaw
import com.ichi2.libanki.importAnkiPackage
import com.ichi2.libanki.importCsvRaw
import com.ichi2.libanki.undoableOp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

suspend fun importAnkiPackageUndoable(input: ByteArray): ByteArray {
val request = ImportAnkiPackageRequest.parseFrom(input)
val path = Uri.encode(request.packagePath, "/")
return withContext(Dispatchers.Main) {
val output = withCol { this.importAnkiPackageRaw(input) }
val changes = OpChangesOnly.parseFrom(output)
undoableOp { changes }
output
val output = withCol { importAnkiPackage(path, request.options) }
undoableOp { output.changes }
output.toByteArray()
}
}

Expand Down
1 change: 0 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ import com.ichi2.anki.model.CardsOrNotes.*
import com.ichi2.anki.model.SortType
import com.ichi2.anki.noteeditor.EditCardDestination
import com.ichi2.anki.noteeditor.toIntent
import com.ichi2.anki.pages.CardInfo.Companion.toIntent
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.previewer.PreviewerFragment
import com.ichi2.anki.receiver.SdCardReceiver
Expand Down
2 changes: 1 addition & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import com.ichi2.anki.cardviewer.Gesture
import com.ichi2.anki.cardviewer.ViewerCommand
import com.ichi2.anki.pages.AnkiServer.Companion.ANKIDROID_JS_PREFIX
import com.ichi2.anki.pages.AnkiServer.Companion.ANKI_PREFIX
import com.ichi2.anki.pages.CardInfo.Companion.toIntent
import com.ichi2.anki.pages.CardInfoDestination
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.reviewer.*
Expand Down Expand Up @@ -1394,6 +1393,7 @@ open class Reviewer :
when (val methodName = uri.substring(ANKI_PREFIX.length)) {
"getSchedulingStatesWithContext" -> getSchedulingStatesWithContext()
"setSchedulingStates" -> setSchedulingStates(bytes)
"i18nResources" -> withCol { i18nResourcesRaw(bytes) }
else -> throw IllegalArgumentException("unhandled request: $methodName")
}
} else if (uri.startsWith(ANKIDROID_JS_PREFIX)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,11 @@ import android.content.Intent
import android.os.Bundle
import android.webkit.WebView
import androidx.activity.OnBackPressedCallback
import androidx.core.os.bundleOf
import com.ichi2.anki.CollectionManager
import com.ichi2.anki.R
import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.anki.hideShowButtonCss
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

class AnkiPackageImporterFragment : PageFragment() {
override val title: String
get() = resources.getString(R.string.menu_import)
override val pageName: String
get() = "import-anki-package"

override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient {
// the back callback is only enabled when import is running and showing progress
Expand All @@ -41,14 +33,11 @@ class AnkiPackageImporterFragment : PageFragment() {
remove()
}
}
val path = arguments?.getString(ARG_FILE_PATH)
?: throw IllegalStateException("No path provided for apkg package to import")
requireActivity().onBackPressedDispatcher.addCallback(this, backCallback)
return AnkiPackageImporterWebViewClient(path, backCallback)
return AnkiPackageImporterWebViewClient(backCallback)
}

class AnkiPackageImporterWebViewClient(
private val path: String,
private val backCallback: OnBackPressedCallback
) : PageWebViewClient() {
/**
Expand All @@ -59,9 +48,7 @@ class AnkiPackageImporterFragment : PageFragment() {
private var isDone = false

override fun onPageFinished(view: WebView?, url: String?) {
val params = Json.encodeToString(path)
// https://github.com/ankitects/anki/blob/main/ts/import-page/index.ts
view!!.evaluateJavascript("anki.setupImportAnkiPackagePage($params);$hideShowButtonCss;") {
view!!.evaluateJavascript(hideShowButtonCss) {
super.onPageFinished(view, url)
}
}
Expand All @@ -81,11 +68,9 @@ class AnkiPackageImporterFragment : PageFragment() {
}

companion object {
private const val ARG_FILE_PATH = "arg_file_path"

fun getIntent(context: Context, filePath: String): Intent {
val args = bundleOf(ARG_FILE_PATH to filePath)
return SingleFragmentActivity.getIntent(context, AnkiPackageImporterFragment::class, args)
val title = context.getString(R.string.menu_import)
return getIntent(context, "import-anki-package$filePath", title, AnkiPackageImporterFragment::class)
}
}
}
57 changes: 0 additions & 57 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfo.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2022 Brayan Oliveira <[email protected]>
*
* 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 com.ichi2.anki.R
import com.ichi2.libanki.CardId

data class CardInfoDestination(val cardId: CardId) {
fun toIntent(context: Context): Intent {
val title = context.getString(R.string.card_info_title)
return PageFragment.getIntent(context, "card-info/$cardId", title)
}
}
5 changes: 1 addition & 4 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import com.ichi2.anki.FilteredDeckOptions
import com.ichi2.anki.OnErrorListener
import com.ichi2.anki.OnPageFinishedCallback
import com.ichi2.anki.R
import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.anki.StudyOptionsActivity
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialog
import com.ichi2.anki.launchCatchingIO
Expand All @@ -61,8 +60,6 @@ class CongratsPage :
PageFragment(),
CustomStudyDialog.CustomStudyListener,
ChangeManager.Subscriber {
override val title: String = ""
override val pageName = "congrats"

private val viewModel by viewModels<CongratsViewModel>()

Expand Down Expand Up @@ -183,7 +180,7 @@ class CongratsPage :

companion object {
fun getIntent(context: Context): Intent {
return SingleFragmentActivity.getIntent(context, CongratsPage::class)
return getIntent(context, path = "congrats", clazz = CongratsPage::class)
}

private fun displayNewCongratsScreen(context: Context): Boolean =
Expand Down
22 changes: 5 additions & 17 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ import com.ichi2.anki.hideShowButtonCss
* Anki page used to import text/csv files
*/
class CsvImporter : PageFragment() {
override val title: String
get() = resources.getString(R.string.menu_import)

override val pageName = "import-csv"

override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient {
// the back callback is only enabled when import is running and showing progress
Expand All @@ -43,14 +39,12 @@ class CsvImporter : PageFragment() {
remove()
}
}
val path = arguments?.getString(ARG_KEY_PATH) ?: throw Exception("missing path")
super.onCreate(savedInstanceState)
requireActivity().onBackPressedDispatcher.addCallback(this, backCallback)
return CsvImporterWebViewClient(path, backCallback)
return CsvImporterWebViewClient(backCallback)
}

class CsvImporterWebViewClient(
val path: String,
inner class CsvImporterWebViewClient(
private val backCallback: OnBackPressedCallback
) : PageWebViewClient() {
/**
Expand All @@ -61,8 +55,7 @@ class CsvImporter : PageFragment() {
private var isDone = false

override fun onPageFinished(view: WebView?, url: String?) {
// from upstream: https://github.com/ankitects/anki/blob/678c354fed4d98c0a8ef84fb7981ee085bd744a7/qt/aqt/import_export/import_csv_dialog.py#L49
view!!.evaluateJavascript("anki.setupImportCsvPage('$path');$hideShowButtonCss") {
view!!.evaluateJavascript(hideShowButtonCss) {
super.onPageFinished(view, url)
}
}
Expand All @@ -82,18 +75,13 @@ class CsvImporter : PageFragment() {
}

companion object {
/** Key of [CsvImporter]'s argument that holds the path of the file to be imported */
private const val ARG_KEY_PATH = "csvPath"

/**
* @param filePath path of the csv file that will be imported, which should be accessible by AnkiDroid
* @return an intent to open the [CsvImporter] page on [SingleFragmentActivity]
*/
fun getIntent(context: Context, filePath: String): Intent {
val arguments = Bundle().apply {
putString(ARG_KEY_PATH, filePath)
}
return SingleFragmentActivity.getIntent(context, CsvImporter::class, arguments)
val title = context.getString(R.string.menu_import)
return getIntent(context, "import-csv$filePath", title, CsvImporter::class)
}
}
}
41 changes: 3 additions & 38 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/DeckOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@ package com.ichi2.anki.pages
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import android.webkit.WebView
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.FragmentActivity
import anki.collection.OpChanges
import com.ichi2.anki.CollectionManager
import com.ichi2.anki.OnPageFinishedCallback
import com.ichi2.anki.R
import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.anki.dialogs.DiscardChangesDialog
import com.ichi2.anki.withProgress
import com.ichi2.annotations.NeedsTest
Expand All @@ -38,11 +35,7 @@ import timber.log.Timber

@NeedsTest("pressing back: icon + button should go to the previous screen")
@NeedsTest("15130: pressing back: icon + button should return to options if the manual is open")
@NeedsTest("saveAndExit closes screen")
class DeckOptions : PageFragment() {
override val title: String
get() = resources.getString(R.string.menu__deck_options)
override val pageName = "deck-options"

// handle going back from the manual
private val onBackCallback = object : OnBackPressedCallback(false) {
Expand All @@ -65,48 +58,20 @@ class DeckOptions : PageFragment() {
}

override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient {
val deckId = arguments?.getLong(ARG_DECK_ID)
?: throw Exception("missing deck ID")

requireActivity().onBackPressedDispatcher.addCallback(this, onBackSaveCallback)
requireActivity().onBackPressedDispatcher.addCallback(this, onBackCallback)
return DeckOptionsWebClient(deckId).apply {
return PageWebViewClient().apply {
onPageFinishedCallback = OnPageFinishedCallback { view ->
Timber.v("canGoBack: %b", view.canGoBack())
onBackCallback.isEnabled = view.canGoBack()
}
}
}

@Suppress("unused")
fun saveAndExit() {
// dispatch Ctrl+Enter
val downEvent = KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, KeyEvent.META_CTRL_ON)
val upEvent = KeyEvent(0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, KeyEvent.META_CTRL_ON)
webView.dispatchKeyEvent(downEvent)
webView.dispatchKeyEvent(upEvent)
}

class DeckOptionsWebClient(val deckId: Long) : PageWebViewClient() {
override val promiseToWaitFor: String
get() = "\$deckOptions"

override fun onPageFinished(view: WebView?, url: String?) {
// from upstream: https://github.com/ankitects/anki/blob/678c354fed4d98c0a8ef84fb7981ee085bd744a7/qt/aqt/deckoptions.py#L55
view!!.evaluateJavascript("const \$deckOptions = anki.setupDeckOptions($deckId);") {
super.onPageFinished(view, url)
}
}
}

companion object {
const val ARG_DECK_ID = "deckId"

fun getIntent(context: Context, deckId: Long): Intent {
val arguments = Bundle().apply {
putLong(ARG_DECK_ID, deckId)
}
return SingleFragmentActivity.getIntent(context, DeckOptions::class, arguments)
val title = context.getString(R.string.menu__deck_options)
return getIntent(context, "deck-options/$deckId", title, DeckOptions::class)
}
}
}
Expand Down
Loading

0 comments on commit 14813c1

Please sign in to comment.